# smolmail Test Vectors, version 1.2 Known-answer tests for [SPEC.md](SPEC.md), generated from the reference implementation by [vectors.py](vectors.py). [vectors.json](vectors.json) carries the same values in a form a test harness can load; this file is for reading alongside the specification. Work through them in order. Derivation first (§2), because every later vector depends on it, then an envelope you can seal and unseal (§5), then the wire frames (§4, §6.1, §7). Finish with the rejections: they are the ones that catch an implementation which decrypts without verifying. Hex throughout, unless a field name says otherwise. The two masters are test data and the private keys here are public. Never use them for anything. ## Labels (§11) Every hash, signature and MAC is domain-separated by one of these, prefixed to the input as raw bytes with no separator or length: - `LABEL_IDENTITY` = `smolmail/1 identity` - `LABEL_ACCEPT` = `smolmail/1 accept` - `LABEL_SEAL` = `smolmail/1 seal` - `LABEL_MSG` = `smolmail/1 msg` - `LABEL_ID` = `smolmail/1 id` - `LABEL_MAC` = `smolmail/1 mac` - `LABEL_AUTH` = `smolmail/1 auth` - `LABEL_ROTATE` = `smolmail/1 rotate` - `LABEL_REGISTER` = `smolmail/1 register` - `PROLOGUE` = `smolmail/1` ## §2 Identity `seed_n = HKDF-SHA256(master, salt = "", info = "smolmail/1 identity" || n)`, with `n` a big-endian u32. The Ed25519 public key of that seed *is* the identity. The X25519 keypair comes from the same key via libsodium's conversions, and the accept key is derived without the index so it survives rotation. ### alice, rotation index 0 - `master`: `000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f` - `rotation_index`: `0` - `seed`: `f2fd61c1fba591a06eadf25ab3252caa1885b615f35fe9eab89dbf64ed233788` - `identity_key`: `da6f2bc263adece0989fa5c85785d11aa8baf822f01db3f1149416eaf1465292` - `x25519_private`: `205ef2abb8830bfaf41c910fe2fa2a67f3b7b5c7f87c74001bacbedea0be3a7a` - `x25519_public`: `0c2dfdd8a679c9ca05c908651396b36dd4da1cf6ac3fc5b0037bde8d3feb506b` - `base32`: `3jxsxqtdvxwobge7uxefpbordkulv6bc6ao3h4iusqlov4kgkkja` - `fingerprint`: `3jxs xqtd vxwo bge7 uxef` - `uri`: `smol://alice@example.org/3jxsxqtdvxwobge7uxefpbordkulv6bc6ao3h4iusqlov4kgkkja` ### alice, rotation index 1 - `master`: `000102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f` - `rotation_index`: `1` - `seed`: `01bcae47fc0b45b9cfd8f6b6cc7ec094970e517715d9c037354646f37fd82dea` - `identity_key`: `cb9046928dd2bede87ddc5ca42378fbd6f987e425b34a2801f74b768da39e466` - `x25519_private`: `884e39cd42c09e5817059634c94c3855b93ebda61f864cc951c4d6e89389ea6b` - `x25519_public`: `d9c834e4238b16e5f92bcf3fcb78fd163dec6b1c6b6ba4867f5526bed5bd6e3c` - `base32`: `zoieneun2k7n5b65yxfeen4pxvxzq7sclm2kfaa7os3wrwrz4rta` - `fingerprint`: `zoie neun 2k7n 5b65 yxfe` - `uri`: `smol://alice@example.org/zoieneun2k7n5b65yxfeen4pxvxzq7sclm2kfaa7os3wrwrz4rta` ### bob, rotation index 0 - `master`: `202122232425262728292a2b2c2d2e2f303132333435363738393a3b3c3d3e3f` - `rotation_index`: `0` - `seed`: `469fdf277869a739339c3c8d0877ca7d8bbd27170238aa61681787e5feafba8c` - `identity_key`: `37b39278f08beadeecc5961640eb7634bd664f12ed40c3d69482045607c9471c` - `x25519_private`: `e0d577fb7fe95cf8f8e3a7d500e060155e484f89ef46c4f208fce77ccd485e48` - `x25519_public`: `0814610bf746f1e6f33eb9275c5a8e3b43ecf92fa442f144444779d62fe1144e` - `base32`: `g6zze6hqrpvn53gfsyleb23wgs6wmtys5vamhvuuqicfmb6ji4oa` - `fingerprint`: `g6zz e6hq rpvn 53gf syle` - `uri`: `smol://bob@example.org/g6zze6hqrpvn53gfsyleb23wgs6wmtys5vamhvuuqicfmb6ji4oa` ### Accept keys and tokens (§5.8) alice's accept key, and the token she issues to bob. The accept key is derived without the rotation index, so it and every token from it survive rotation. - `alice_accept_key`: `2c18d0eeaa9b2333f3ecd41391131ea13f10aa35903389d860c25265545026ae` - `bob_accept_key`: `eff6fd323304674053b55a8b6a804b6a9fdbd111faad802763c1feced48259ee` - `alice_token_for_bob`: `084e74a6dec8ed8101672225450265e5fa3dcbe3a69455569ce1ffc254df1885` - `alice_token_for_bob_base32`: `bbhhjjw6zdwycalheisukatf4x5d3s7du2kfkvu44h74evg7dccq` - `bob_token_for_alice_0`: `411bccb54d51808fcf329ca609e8d8dac866e556b2a90bb4374979cb0d8689b7` - `alice_token_for_bob_rotated`: `96ddeaeabc81dadf328898de5adec032eef7d98d799fed54b8b737282090831b` `alice_token_for_bob_rotated` is the token alice would issue to bob's index-1 key. It differs from the one bob already holds, which is why §5.8 says a token is derived from the correspondent's identity *as it stood when they were accepted*: bob's rotation does not invalidate the token he was given. ## §3 Addressing The short form is resolved by the server; the smol:// form carries the key and needs no server to be trusted. 1961 is the default port and is omitted from the short form. ### Usernames | username | valid | | --- | --- | | `a` | yes | | `a0` | yes | | `alice` | yes | | `al-ice` | yes | | `a.b-c_d` | yes | | `xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx` | yes | | `(empty)` | no | | `-alice` | no | | `alice-` | no | | `.alice` | no | | `al..ice` | no | | `a._b` | no | | `a-_b` | no | | `Alice` | no | | `xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx` | no | | `al ice` | no | | `alice@` | no | | `ali/ce` | no | ### Addresses | input | user | host | port | identity | | --- | --- | --- | --- | --- | | `alice@example.org` | `alice` | `example.org` | 1961 | resolved | | `alice@example.org:1961` | `alice` | `example.org` | 1961 | resolved | | `alice@example.org:2000` | `alice` | `example.org` | 2000 | resolved | | `smol://alice@example.org/3jxsxqtdvxwobge7uxefpbordkulv6bc6ao3h4iusqlov4kgkkja` | `alice` | `example.org` | 1961 | `da6f2bc263adece0…` | Refused: - `smol://alice@example.org` — SmolError: smol://alice@example.org: smol:// address carries no key - `smol://alice@example.org/aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa` — SmolError: smol://alice@example.org/aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa: key is 31 bytes, expected 32 - `smol://alice@example.org/not-base32!` — SmolError: smol://alice@example.org/not-base32!: undecodable key: Non-base32 digit found - `-alice@example.org` — SmolError: '-alice' must begin and end with a letter or digit and may not contain two separators in a row ### Fingerprint - `identity`: `da6f2bc263adece0989fa5c85785d11aa8baf822f01db3f1149416eaf1465292` - `encoded`: `3jxsxqtdvxwobge7uxefpbordkulv6bc6ao3h4iusqlov4kgkkja` - `fingerprint`: `3jxs xqtd vxwo bge7 uxef` - `fingerprint_note`: `the first 20 base32 characters in groups of four: 100 bits, so a collision costs ~2^100` ## §5 Messages Each vector pins the ephemeral `esk` that §5.2 would draw at random and the `time` that §5.3 would take from the clock. Nothing else in the protocol is randomised, so with those two fixed an envelope reproduces byte for byte. Build one in this order: agree on `x25519_shared`, derive `seal_key`, assemble `payload_header`, sign `signed_preimage`, concatenate the payload, then encrypt it under `aad` with an all-zero nonce. If your `seal_key` matches and your envelope does not, the fault is in the payload layout; if `x25519_shared` already differs, it is in §2's map. `accept_mac` is what a sender holding the recipient's token attaches to `SEND` (§5.8); `message_id` is what the server returns. The full payload plaintext and the whole `SEND` request body are in vectors.json as `payload` and `send_body`. ### empty-body body_len 0. The payload is 109 bytes and the envelope 194. - `sender`: `bob[0]` - `recipient`: `alice[0]` - `body`: (empty) - `body_len`: `0` - `time`: `1767225600` - `padded`: `false` - `esk`: `4040404040404040404040404040404040404040404040404040404040404040` - `epk`: `d7b5e81d336e578b13b8d706e82d061e3038c96bce66cdcf50d566b96ddbba10` - `x25519_shared`: `383fc0e605a085e558481bcf53dfc0247a6f2c1ad46fe659953cf36874000469` - `seal_key`: `d035954d97b00442b87ce8025cafe438c7791079d407dc11b75915ace169609c` - `aad`: `534d4f4c01da6f2bc263adece0989fa5c85785d11aa8baf822f01db3f1149416eaf1465292d7b5e81d336e578b13b8d706e82d061e3038c96bce66cdcf50d566b96ddbba10` - `payload_header`: `0137b39278f08beadeecc5961640eb7634bd664f12ed40c3d69482045607c9471c000000006955b90000000000` `signed_preimage` ``` 736d6f6c6d61696c2f31206d7367da6f2bc263adece0989fa5c85785d11aa8baf822f01db3f1 149416eaf1465292d7b5e81d336e578b13b8d706e82d061e3038c96bce66cdcf50d566b96ddb ba100137b39278f08beadeecc5961640eb7634bd664f12ed40c3d69482045607c9471c000000 006955b90000000000 ``` - `signature`: `e41a00f14ce5dd28ca4242be7f1d4e92c4ddc5256a9071982462da20644cb136629e0c6dd817db8b0d5dcd2d23239f0b807586193acea67a3abfb339804e3501` - `payload_len`: `109` - `envelope_len`: `194` `envelope` ``` 534d4f4c01da6f2bc263adece0989fa5c85785d11aa8baf822f01db3f1149416eaf1465292d7 b5e81d336e578b13b8d706e82d061e3038c96bce66cdcf50d566b96ddbba10786f5f9e9e91dd 4e29fc0a8e9516fcde856e9f6dcf5010ba87e7878bf99db9030cca7b73d61fef8a4e23e24628 f0e75b993c647361e41bd53d6ddd3a565b2ba334afaeb191f13dc801d9e7d9eeffad7eae12b0 e2e59243c7a523db3fcdb9c21e3b83508f4905624e4ae5234ba51cb5633813ffff93b60de3f1 ca8cd8a8 ``` - `envelope_sha256`: `1a37555e369665f562b6a492de97a8c9cf024764b2fae32bf7bce33ebc9bc88f` - `message_id`: `289dd78f0fb9ec8e27b1b648b1fc4cd36e388cad63e5320e8f331315998fc451` - `accept_mac`: `1ce7f575843fa08ca8976213efbb951c8e13f119ff578da8c3f4091a15c284e5` ### unpadded The minimal form: 69 + 45 + 11 + 64 + 16 bytes. Start here. - `sender`: `bob[0]` - `recipient`: `alice[0]` - `body`: `68656c6c6f20616c696365` - `body_len`: `11` - `time`: `1767225600` - `padded`: `false` - `esk`: `4141414141414141414141414141414141414141414141414141414141414141` - `epk`: `7a1a4e709bf085ac494aba0469b9b1eda0ab1f78b16aabb79ffeda90623e8522` - `x25519_shared`: `012b8e969fb857162e7d00cef9e68b60ebc30a858439bf0c0e256b8807f70769` - `seal_key`: `c4c72488dc2b6582952cb297d5d54b05b43ec7540cfdc173e55010f38d6444ed` - `aad`: `534d4f4c01da6f2bc263adece0989fa5c85785d11aa8baf822f01db3f1149416eaf14652927a1a4e709bf085ac494aba0469b9b1eda0ab1f78b16aabb79ffeda90623e8522` - `payload_header`: `0137b39278f08beadeecc5961640eb7634bd664f12ed40c3d69482045607c9471c000000006955b9000000000b` `signed_preimage` ``` 736d6f6c6d61696c2f31206d7367da6f2bc263adece0989fa5c85785d11aa8baf822f01db3f1 149416eaf14652927a1a4e709bf085ac494aba0469b9b1eda0ab1f78b16aabb79ffeda90623e 85220137b39278f08beadeecc5961640eb7634bd664f12ed40c3d69482045607c9471c000000 006955b9000000000b68656c6c6f20616c696365 ``` - `signature`: `f4b5f898318a0c7da2f779a24972f1b51041bce5723d54e340f9887199c2f299b40b76ca3097562928cff3c2d8e02e7e78492f7f80ed6b0f784e1015b3f3b20c` - `payload_len`: `120` - `envelope_len`: `205` `envelope` ``` 534d4f4c01da6f2bc263adece0989fa5c85785d11aa8baf822f01db3f1149416eaf14652927a 1a4e709bf085ac494aba0469b9b1eda0ab1f78b16aabb79ffeda90623e85223f096c1be498f7 9a436bb6e96b7d425fc1173bd34c39f824e44c886a0291c1ce88d5956af3ee9d13b4c002eb50 63388392b4777356a96d32e8940477577337b48af677c773482b47c49e558e7f0dd5b93396e5 f38e3b7b01d4e2784bf4bd3df0aa84efabe12925c7522c8ca9ab867bd64aa38f1488bf2cac84 f2d6fd1f6657a67991393a5607e721 ``` - `envelope_sha256`: `8594cdb21ec3373f1516253e7db829e18471c066d8a891f71e9c75d547a696c5` - `message_id`: `75f74029f5e6a60dae846767622c09177ec75ea8de171b1b4314e44faac26d35` - `accept_mac`: `5cb318c5db75b0f37f8b3b8bf31a5899e5f673416c0c442a3d01abc8019b01b4` ### padded The same message with §5.3 padding to a 1024-byte multiple. A receiver must ignore the trailing zeros and trust body_len. - `sender`: `bob[0]` - `recipient`: `alice[0]` - `body`: `68656c6c6f20616c696365` - `body_len`: `11` - `time`: `1767225600` - `padded`: `true` - `esk`: `4242424242424242424242424242424242424242424242424242424242424242` - `epk`: `132c442be010fbd57e72603328aa76e71fccc1503aae219327d14d9c9993f472` - `x25519_shared`: `2957671c03ec2f21c2d1a1c9e743564016a3107618f53077f02aff745c90ef02` - `seal_key`: `db77b3dc494a2b299eadbbbdd3c3c0cd5e44a6b8c7ad7490729a63905668fbf4` - `aad`: `534d4f4c01da6f2bc263adece0989fa5c85785d11aa8baf822f01db3f1149416eaf1465292132c442be010fbd57e72603328aa76e71fccc1503aae219327d14d9c9993f472` - `payload_header`: `0137b39278f08beadeecc5961640eb7634bd664f12ed40c3d69482045607c9471c000000006955b9000000000b` `signed_preimage` ``` 736d6f6c6d61696c2f31206d7367da6f2bc263adece0989fa5c85785d11aa8baf822f01db3f1 149416eaf1465292132c442be010fbd57e72603328aa76e71fccc1503aae219327d14d9c9993 f4720137b39278f08beadeecc5961640eb7634bd664f12ed40c3d69482045607c9471c000000 006955b9000000000b68656c6c6f20616c696365 ``` - `signature`: `000e182ed5e1e10fc9ab0d1e358d54fb6ffb8fe9ea097fb795b900dfe3b9914734a11cfb0ddff7a5ce47d9b1f66fc48022b7402e2fbae0f32762632db59e7507` - `payload_len`: `1024` - `envelope_len`: `1109` `envelope` ``` 534d4f4c01da6f2bc263adece0989fa5c85785d11aa8baf822f01db3f1149416eaf146529213 2c442be010fbd57e72603328aa76e71fccc1503aae219327d14d9c9993f47269e94cda066826 23d97aed6f33fdd2ff38d48811450881350eb826904757f1e3e30ceeb0989c56e4638131f409 68350f507f2d61d2320abb5cc3bc433340094c37bcc350abf0e7910a672879527c99e7a9f77c bff5e9d99138c56f75e9a98bf4128107a83176666c5db76298e338ce4be914cbecaca5ea11f1 4555cb7028ac1ccf41d0b330beada77c61eb42cab21097b005d1cf1ad60b5bfcd137a02ecd9a af65a4692882d75e73e52d6ebcfe47bfead71ac9e54d7b1ac275aaf28a192666930324091049 3ffdd92e396387dbfff545f4d8d6b598fcb4a79f48d681f03c70e7ee378bb2cef91c9f744793 4d19aaaf36fd38434eef7dfcb2572b51ab49182278426cfb11f72614130a01907e1104ad5e27 10072041085179eac48281396bbcc5de0f2f60d89934a70b4583dda1b45188609b7d0f959559 38fb49aa2d61ad0c63d69a7f8da875b957bfff6f9b7d83a7ebb1e05f4099033e81cdaae5b0ab 83960871f3da11ceabcdd710d589948e7cd7a0e3eedee7941ad250b224d8869e657b0af53d22 ab8502919e40959acd69e303879d2ed2a4487e0d7d5a2203f886e2dd95c41655a3c4c09bcbb6 b5fbff92f1694d5e1ad5c470bbe33eaa3254e416f72d32be96d46ecaf6fc12bd891f8d3a0dc8 c36403b23f7875fa0afc518a307dcd3d7cb8846bbfdf40fedf49e3ea87a5f378050fa2f6ea8e a86a422c58f8e7c9a077cd3fbc69c4837d748a0d32678cc7f8b482d09e3c2c9eb5037cdf2082 4be0f0c1fe26893d7e3b04a4a16ed8c7910fbf1a106a12d4c145dae793b46e36176f3c621c30 75adec0e445c033dc6d4fbe0f3c7f9419604361435e2af332cc428b038ab0e339c07248f8ac9 fc520f722558ff015b372a5d9f90a867f606b63329b21dcd05587f13e3abe40be2f5c9177048 c69168f087e071aecccff1eb3f04f95d9557dd6a40c37338765bff6de1861ca04e28a92d372e fb92103a982d760aa89301b60c8d9a591c39492dad4467053f3c85ca226777a591434b814bdf 86d4d7557665bdf118da32e2396eba2ca3dc24731690eee9bae9398f6b9ca81f449a486ef14f 7db9c2c8e330c4b56569b24bdf1d53961d0338fd38e7ac345a1bccbd2ead3a2a133b798762bb ddaf60f7e743b2ab0bc9f9b14b7755b02f9068ab9b4a8f154d6e9d6f61013281a6a7a69ebaa2 80f0fd7a7bc1734ddc37ef0af2d0628d5d6f7a62d345648e03b6aa84d2470a0883e79e962faa 65b3547d2b4eac386cdcdcc2afa8ebf525183854d8baafbd09691edaa73c193ad54f99bea34e f8a2fd03ef6f869bd28bafb8377affdab5867cec7609eff5834d4cb7c9820a07fb17aebc6827 ee1c7505f820d9be04973c0b264bb3be34d54cb2e1ac4edf437a3a065a85c4158af88952721c 3d83195f898e514ba9e751060be46d2a6067e99c99a61d2959cb0d1b7ca6e76c207d26a50509 0fa3007a406471 ``` - `envelope_sha256`: `41a93d239e7da918e1e6480b724b8e23eeb39ddd454b889f6a55934658c143b2` - `message_id`: `ff849aa8b573dfc10dc5ac731b862ba1205f42c81a014744f2812d3bf1d62a2e` - `accept_mac`: `2b0a0b0804a78a32f47e461b8ed06e6c1a21ed750b2b33290cc91f884fb86ca0` ### utf8 body_len counts bytes, not characters: 29 bytes, 22 characters. - `sender`: `bob[0]` - `recipient`: `alice[0]` - `body`: `4772c3bcc39f65206175732064656d204d65736820e2809420f09f9bb00a` - `body_len`: `30` - `time`: `1767225600` - `padded`: `false` - `esk`: `4343434343434343434343434343434343434343434343434343434343434343` - `epk`: `cdefd8783a91b446640e2e1f95599db35e484a0071bd2182b3b60d0812c10c70` - `x25519_shared`: `40ff868360e1f61dd53a383f4e8d96205ac1eab3dea7f1c69f9a8d44f853da79` - `seal_key`: `3bab319a2a1e80a93c2639891f9dce11c35e8cbc558fea02f3c3ef494276b54b` - `aad`: `534d4f4c01da6f2bc263adece0989fa5c85785d11aa8baf822f01db3f1149416eaf1465292cdefd8783a91b446640e2e1f95599db35e484a0071bd2182b3b60d0812c10c70` - `payload_header`: `0137b39278f08beadeecc5961640eb7634bd664f12ed40c3d69482045607c9471c000000006955b9000000001e` `signed_preimage` ``` 736d6f6c6d61696c2f31206d7367da6f2bc263adece0989fa5c85785d11aa8baf822f01db3f1 149416eaf1465292cdefd8783a91b446640e2e1f95599db35e484a0071bd2182b3b60d0812c1 0c700137b39278f08beadeecc5961640eb7634bd664f12ed40c3d69482045607c9471c000000 006955b9000000001e4772c3bcc39f65206175732064656d204d65736820e2809420f09f9bb0 0a ``` - `signature`: `86372500958b7808f6fb1878d40ccc9a2b090fbb042f834b6e131ee1c7d55ef3be7ecb44db86c59bee9dc4f2268fce878e0d6e79e046969f3667bbb8b6fd110e` - `payload_len`: `139` - `envelope_len`: `224` `envelope` ``` 534d4f4c01da6f2bc263adece0989fa5c85785d11aa8baf822f01db3f1149416eaf1465292cd efd8783a91b446640e2e1f95599db35e484a0071bd2182b3b60d0812c10c70315b93e0580e4c e845678e9aa71eeb8bf2f8c3155a8c1fd58dc43c91095e0a19032a91231f3f7ef11167dac73e 296e98c921c15c8d02e24747df1ffa600818abfb6858aa82184277da1d1fd02d1d59ada01941 8a2c708a7521e6a0f1e8e55f24f46d0bfa7d9c1ad761580f320f5c3248c18aac5158c0296992 6f427d921fee8ba4ccf2bff233733e64d5e3b50757f8f5b880d1f869651c9a186608 ``` - `envelope_sha256`: `fcf78b183a0c2fad26f36b15e6cd222d1e864f48c7eea616f66aa65a14872b7c` - `message_id`: `82c6d8c341ea821e4558dc6bb35f533e399a89646d9023437802b1d2499f2b88` - `accept_mac`: `b221784d76eb2d52517d142912139ab0f6e61900ff35eed45998cb459683cf68` ### frontmatter §5.5 frontmatter carrying the reserved Reply-To (§5.7) and Accept (§5.8) fields. Both are only meaningful because the signature covers them. - `sender`: `alice[0]` - `recipient`: `bob[0]` `body` ``` 2d2d2d0a5375626a6563743a20746865207468696e670a5265706c792d546f3a20736d6f6c3a 2f2f616c696365406578616d706c652e6f72672f336a7873787174647678776f626765377578 656670626f72646b756c7636626336616f336834697573716c6f76346b676b6b6a610a416363 6570743a20626268686a6a77367a64777963616c68656973756b617466347835643373376475 326b666b7675343468373465766737646363710a2d2d2d0a48657265206973206120746f6b65 6e20736f20796f7572206d61696c20736b697073206d7920726571756573747320746965722e 0a ``` - `body_len`: `229` - `time`: `1767225600` - `padded`: `false` - `esk`: `4444444444444444444444444444444444444444444444444444444444444444` - `epk`: `ff2ee45601ec1b67310c7790404585ae697331eee1c1f8cf2419731c1fff3e6b` - `x25519_shared`: `07c5ae79c7568952aa78668c613389e4ecdd2f61f207618532fb3c8c8a26f213` - `seal_key`: `4dd79e54e611ac322ac0ace7e7a64b2c2139d422097f939c603ee6dd9843f7cc` - `aad`: `534d4f4c0137b39278f08beadeecc5961640eb7634bd664f12ed40c3d69482045607c9471cff2ee45601ec1b67310c7790404585ae697331eee1c1f8cf2419731c1fff3e6b` - `payload_header`: `01da6f2bc263adece0989fa5c85785d11aa8baf822f01db3f1149416eaf1465292000000006955b900000000e5` `signed_preimage` ``` 736d6f6c6d61696c2f31206d736737b39278f08beadeecc5961640eb7634bd664f12ed40c3d6 9482045607c9471cff2ee45601ec1b67310c7790404585ae697331eee1c1f8cf2419731c1fff 3e6b01da6f2bc263adece0989fa5c85785d11aa8baf822f01db3f1149416eaf1465292000000 006955b900000000e52d2d2d0a5375626a6563743a20746865207468696e670a5265706c792d 546f3a20736d6f6c3a2f2f616c696365406578616d706c652e6f72672f336a78737871746476 78776f626765377578656670626f72646b756c7636626336616f336834697573716c6f76346b 676b6b6a610a4163636570743a20626268686a6a77367a64777963616c68656973756b617466 347835643373376475326b666b7675343468373465766737646363710a2d2d2d0a4865726520 6973206120746f6b656e20736f20796f7572206d61696c20736b697073206d79207265717565 73747320746965722e0a ``` - `signature`: `23e0b6bd5660ab109144e07b24affb7298041dafe908a469ab28c120f812b91dbcc7cee0763d058df4357d74ef4dee85f42da50dffdc66fb8604288a3c3d0000` - `payload_len`: `338` - `envelope_len`: `423` `envelope` ``` 534d4f4c0137b39278f08beadeecc5961640eb7634bd664f12ed40c3d69482045607c9471cff 2ee45601ec1b67310c7790404585ae697331eee1c1f8cf2419731c1fff3e6b7d16509bc2c568 3501cacd195740772232cdb04f5375e55dac3d49e258524c0eca1819d6911503a76d1b80e2e2 048947659c9925faa4e2710420d0be9110cd216f651808f4132dc13d6a91c55d9ac653b161ad 63cc70b7c9eac3b89d4994b04e791b195ca148845649a3a473f7dc26bfd0326e1f65b7559d12 824920c136e502d1c29c3211a3ca7d0782df4655e31123de9d61ebb35fe9fcfd0ecdf0c7e406 854ab7bfddbc818dd839e02ea450fd94124228a8bae41bf020962919de514525304a8f2c512b 8335bbef48af719c340d63a7e38cd6ab40c004601edf67a572062182a15328825f017d10b841 9edf162610ece5884539e8408bd6893a47b5d99d02bd944e98194424333ee1a99aabf600ec83 ae4cabc38c12c0044bc16536d54a65d78df62428b4ba290296986b19d8e143cad25ee6c20351 5c3dcb3907f3adab87ec4dd4d5cdbfe24621beb2d4901939a02df296b67c996fef0b84fc591c 87b9dc35be ``` - `envelope_sha256`: `4cd667f09da015acc5c6c1f57e57181334b89a11c2d7d543e4dcb2bf012bd698` - `message_id`: `e6a52f744a8c0eab0c0a72c56ef51af96b83d9721d38dc669be38ca2c272f498` - `accept_mac`: `8589379776f7d005c016593b5e04f624d7530f405213639361ab2a127004cd40` ### superseded-key Sealed to alice's index-0 key while she is at index 1 (§7). She opens it with the retained key, which is re-derivable from the master alone. - `sender`: `bob[0]` - `recipient`: `alice[0]` - `body`: `73656e74206265666f726520796f7520726f74617465640a` - `body_len`: `24` - `time`: `1767225600` - `padded`: `false` - `esk`: `4545454545454545454545454545454545454545454545454545454545454545` - `epk`: `3286894cd2845a6db6a28fbf0677605f80e5a62385bf4e10a790ae5fde36736b` - `x25519_shared`: `bf14188f69b809b1c944f8d46c1d4a91f641b741537b88d98622d7f2ac310434` - `seal_key`: `7367d84d99359d719fdb9fceb49b29c19b14636dd4fc2896774061d110973cc8` - `aad`: `534d4f4c01da6f2bc263adece0989fa5c85785d11aa8baf822f01db3f1149416eaf14652923286894cd2845a6db6a28fbf0677605f80e5a62385bf4e10a790ae5fde36736b` - `payload_header`: `0137b39278f08beadeecc5961640eb7634bd664f12ed40c3d69482045607c9471c000000006955b90000000018` `signed_preimage` ``` 736d6f6c6d61696c2f31206d7367da6f2bc263adece0989fa5c85785d11aa8baf822f01db3f1 149416eaf14652923286894cd2845a6db6a28fbf0677605f80e5a62385bf4e10a790ae5fde36 736b0137b39278f08beadeecc5961640eb7634bd664f12ed40c3d69482045607c9471c000000 006955b9000000001873656e74206265666f726520796f7520726f74617465640a ``` - `signature`: `4eb267c60e58d0f6acc2a9f0c39e384e16324ddb7bf8c23e14659682af1cfca526e5e72e39663c3d5207c929b0f65982f74ff7d3de4fce80d76bc8a39bbeac04` - `payload_len`: `133` - `envelope_len`: `218` `envelope` ``` 534d4f4c01da6f2bc263adece0989fa5c85785d11aa8baf822f01db3f1149416eaf146529232 86894cd2845a6db6a28fbf0677605f80e5a62385bf4e10a790ae5fde36736b4272b58c6b941f f140f69144dc10f1d49a0f9603e7a5a97718edc2e0617631d2fed71776274b6d7d2653c1fa88 9af93c9d57fbfd0d0b0ced3f8efdf59adaa23e3101c671d55850adbbb7d776c5f1a1296b6b46 68041c0575d317b2e7bc796894091313cbf1c6be2382fe26229ba9bcfcee3281fd6b55731e06 bf72bdd73efef8b4c32c6a269a2036fc272885f0f6551f9322f727ab ``` - `envelope_sha256`: `57c33559dc31934cae4d41e99954911422178b4a54a7c7cf5a8b3174485dee37` - `message_id`: `292854907f2bc92223edabf57ceead7276402ee3569b18d2d0d40b0e2c50886b` - `accept_mac`: `f417c61474e4c15bbecf8586a8b1adf37a03106aea0ef818a4b970b4e8d429e9` ### rotated-key The same correspondents after alice's rotation. Only `to` changes; her accept token does not. - `sender`: `bob[0]` - `recipient`: `alice[1]` - `body`: `73656e7420616674657220796f7520726f74617465640a` - `body_len`: `23` - `time`: `1767225600` - `padded`: `false` - `esk`: `4646464646464646464646464646464646464646464646464646464646464646` - `epk`: `a28a7c44ede257d664fbf156affa7da8abb3ae74b9fee8d7a2078543504e1a75` - `x25519_shared`: `e8265154d3d8063d89c7b591427fab6ae3b3207bc8ba87d287c2c10bcbfb5b4a` - `seal_key`: `b4e8a0876228c50744d1f3cde417d6299be612b485554300e44434e2f9446106` - `aad`: `534d4f4c01cb9046928dd2bede87ddc5ca42378fbd6f987e425b34a2801f74b768da39e466a28a7c44ede257d664fbf156affa7da8abb3ae74b9fee8d7a2078543504e1a75` - `payload_header`: `0137b39278f08beadeecc5961640eb7634bd664f12ed40c3d69482045607c9471c000000006955b90000000017` `signed_preimage` ``` 736d6f6c6d61696c2f31206d7367cb9046928dd2bede87ddc5ca42378fbd6f987e425b34a280 1f74b768da39e466a28a7c44ede257d664fbf156affa7da8abb3ae74b9fee8d7a2078543504e 1a750137b39278f08beadeecc5961640eb7634bd664f12ed40c3d69482045607c9471c000000 006955b9000000001773656e7420616674657220796f7520726f74617465640a ``` - `signature`: `857ef01e8bd0d7aee6650a86d189c9cb384c1bf6d1cc47c8666e67d88270d0d1b10a2b53388c8a9aca1c6fc0645a40cd8cb4f8af58cdc2e06801918e4e475203` - `payload_len`: `132` - `envelope_len`: `217` `envelope` ``` 534d4f4c01cb9046928dd2bede87ddc5ca42378fbd6f987e425b34a2801f74b768da39e466a2 8a7c44ede257d664fbf156affa7da8abb3ae74b9fee8d7a2078543504e1a75559e854a04d51f d20336516fa2471e8b13784f6597813601f15c8f3d9aa95c049f9671ab843e1d40dc0eccf227 942b48240590da1e753e443129d8ffdaf032d7f5d2298eb7b426bd937faf52af2c0303c33e25 78574c37c0492a2b80a793d539c3ecd13a50dcd6d9ed86510749ae97e0f256d45ad8a4ea0bed 15e50a125933d17e11fc3615f288c5aeeaf706f7dbf279db165e53 ``` - `envelope_sha256`: `b8fbe91f24f6f8969a7a6e2aefaf03a0f8e8e8947d8521baa9fa641c002344c4` - `message_id`: `72c054747b8edd9c710df7ab295ed832ef791e6db4a585821968d8dff9ae3b02` - `accept_mac`: `e7d594c129757cdbf628b354c592cf566f6b40d95fa7f6a7c6be6ca2696917cb` ## §4 and §6.1 Session frames The AUTH signature covers the Noise handshake hash, so it cannot be replayed to another session or server. The REGISTER signature covers the server's static key for the same reason: without it, any party could bind any public key to any username. - `handshake_hash`: `808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9f` - `server_static`: `606162636465666768696a6b6c6d6e6f707172737475767778797a7b7c7d7e7f` - `auth_signed_preimage`: `736d6f6c6d61696c2f312061757468808182838485868788898a8b8c8d8e8f909192939495969798999a9b9c9d9e9f` - `auth_signature`: `26936929ab0ead5f407d69a6516f32d2b871f41d73345b9b7d076d85eea9b6736ea0f522bcff8511c2aea1f8cf0e7a7d3f1f81f3d6d5654a27c5b81e462fa903` `auth_frame` ``` 05616c696365da6f2bc263adece0989fa5c85785d11aa8baf822f01db3f1149416eaf1465292 26936929ab0ead5f407d69a6516f32d2b871f41d73345b9b7d076d85eea9b6736ea0f522bcff 8511c2aea1f8cf0e7a7d3f1f81f3d6d5654a27c5b81e462fa903010001084e74a6dec8ed8101 672225450265e5fa3dcbe3a69455569ce1ffc254df1885 ``` username_len=5 || 'alice' || identity || signature || sync=1 || count=1 || alice's token for bob `register_signed_preimage` ``` 736d6f6c6d61696c2f31207265676973746572606162636465666768696a6b6c6d6e6f707172 737475767778797a7b7c7d7e7f616c696365da6f2bc263adece0989fa5c85785d11aa8baf822 f01db3f1149416eaf1465292 ``` - `register_signature`: `78364170da13b57566df066c66756c29ba4f080e8b75e3503ac7614534cff3486b888455fd5e6ad756edb4ed28567aab8ccc3820b0289d15c48720066818220f` `register_frame` ``` 05616c696365da6f2bc263adece0989fa5c85785d11aa8baf822f01db3f1149416eaf1465292 78364170da13b57566df066c66756c29ba4f080e8b75e3503ac7614534cff3486b888455fd5e 6ad756edb4ed28567aab8ccc3820b0289d15c48720066818220f0000 ``` token_len=0 and cert_len=0: a first registration, no invite token and no rotation certificate ## §7 Key rotation A certificate is 200 bytes and carries no username: the name is covered by both signatures but not transported, so a certificate cannot be replayed against another username bound to the same key. - `username`: `alice` - `old_key`: `da6f2bc263adece0989fa5c85785d11aa8baf822f01db3f1149416eaf1465292` - `new_key`: `cb9046928dd2bede87ddc5ca42378fbd6f987e425b34a2801f74b768da39e466` - `time`: `1767225600` `signed_preimage` ``` 736d6f6c6d61696c2f3120726f74617465616c696365da6f2bc263adece0989fa5c85785d11a a8baf822f01db3f1149416eaf1465292cb9046928dd2bede87ddc5ca42378fbd6f987e425b34 a2801f74b768da39e466000000006955b900 ``` - `sig_old`: `ba3bd58ab28a0bb6758bfda39b95c2e391ef922a60a010e74543c255b6689f5e81bef8ee3f84e88e61959a523429ea2d4d47622df470743caf298a19e43b9b03` - `sig_new`: `58a928e912485548a74c2d8e9d14553a5f90c34411848a8d612fb55600539f762849102530f0ab411914e48879a62b33b1297a18ad774a614283c2268b958a0e` `certificate` ``` da6f2bc263adece0989fa5c85785d11aa8baf822f01db3f1149416eaf1465292cb9046928dd2 bede87ddc5ca42378fbd6f987e425b34a2801f74b768da39e466000000006955b900ba3bd58a b28a0bb6758bfda39b95c2e391ef922a60a010e74543c255b6689f5e81bef8ee3f84e88e6195 9a523429ea2d4d47622df470743caf298a19e43b9b0358a928e912485548a74c2d8e9d14553a 5f90c34411848a8d612fb55600539f762849102530f0ab411914e48879a62b33b1297a18ad77 4a614283c2268b958a0e ``` `resolve_body` ``` cb9046928dd2bede87ddc5ca42378fbd6f987e425b34a2801f74b768da39e46601da6f2bc263 adece0989fa5c85785d11aa8baf822f01db3f1149416eaf1465292cb9046928dd2bede87ddc5 ca42378fbd6f987e425b34a2801f74b768da39e466000000006955b900ba3bd58ab28a0bb675 8bfda39b95c2e391ef922a60a010e74543c255b6689f5e81bef8ee3f84e88e61959a523429ea 2d4d47622df470743caf298a19e43b9b0358a928e912485548a74c2d8e9d14553a5f90c34411 848a8d612fb55600539f762849102530f0ab411914e48879a62b33b1297a18ad774a614283c2 268b958a0e ``` Chain walking: - pinned=old, offered=new, chain=[cert], username=alice → **accept** - same certificate checked as username=mallory → **refuse** (both signatures cover the username) - pinned=old, offered=new, empty chain → **refuse** (a key change needs a chain; absent means ask the user) - sig_new zeroed → **refuse** (the new key must sign too, or the old key alone could hand the username to a key nobody controls) ## §5.5 Frontmatter A flat `Key: value` block, not YAML. A malformed line invalidates the whole block, which is then shown as ordinary body text: frontmatter fails closed toward display, never toward silent discard. | case | input | fields | text | note | | --- | --- | --- | --- | --- | | `no-block` | `'hello\n'` | `{}` | `'hello\n'` | no leading '---\n', so the whole body is text | | `simple` | `'---\nSubject: hi\n---\nbody\n'` | `{'subject': 'hi'}` | `'body\n'` | one field, then the text | | `empty-block` | `'---\n---\n---\nliteral dashes\n'` | `{}` | `'---\nliteral dashes\n'` | an empty block escapes a body that genuinely starts with '---' | | `case-and-duplicates` | `'---\nSubject: first\nsubject: second\nX-Mood: calm\n'…` | `{'subject': 'first', 'x-mood': 'calm'}` | `'b'` | keys are lowercased for comparison and the first occurrence wins | | `value-trimmed` | `'---\nSubject: spaced out \n---\n'` | `{'subject': 'spaced out'}` | `''` | the value is the rest of the line, trimmed | | `colon-in-value` | `'---\nSubject: re: the thing\n---\n'` | `{'subject': 're: the thing'}` | `''` | only the first colon separates | | `no-colon` | `'---\nSubject hi\n---\nbody\n'` | `{}` | `'---\nSubject hi\n---\nbody\n'` | a malformed line invalidates the whole block, which becomes text | | `bad-key` | `'---\nSub ject: hi\n---\nbody\n'` | `{}` | `'---\nSub ject: hi\n---\nbody\n'` | key charset is [A-Za-z0-9-] | | `unterminated` | `'---\nSubject: hi\nbody\n'` | `{}` | `'---\nSubject: hi\nbody\n'` | no closing '---' | | `too-many-keys` | `'---\nK0: v\nK1: v\nK2: v\nK3: v\nK4: v\nK5: v\nK6: v\nK7'…` | `{}` | `'---\nK0: v\nK1: v\nK2: v\nK3: v\nK4: v\nK5: v\nK6: v\nK7'…` | over 64 keys | | `too-large` | `'---\nK: vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv'…` | `{}` | `'---\nK: vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv'…` | over 4 KiB | | `injected-field` | `'---\nSubject: hi\nAccept: aaaaaaaa\n---\nb'` | `{'subject': 'hi', 'accept': 'aaaaaaaa'}` | `'b'` | what a line break in a sender-supplied value produces: a second field, signed and indistinguishable from an intended one. A client building frontmatter MUST refuse a value containing a line break. | Long inputs are clipped here; vectors.json has them whole. ## Rejections Inputs a conformant implementation refuses. The envelope cases are mutations of one valid message, listed with the reference's own error, so a client can be tested against its own failure path. Each envelope is a mutation of this valid one: `valid_baseline` ``` 534d4f4c01da6f2bc263adece0989fa5c85785d11aa8baf822f01db3f1149416eaf1465292c3 06fb0ef2bf8b7f93bad98155fa37daec74db0c4cbeda6c6f1dba9d3655825293a846f5413d3a 945f8aa55bdc4f0fffd51e4f59624b753b1691571500e2db82aa003ffedd16ca5125e2abdfc4 dc05c7c76b3d13e7aaee7c7d9eb6702bb90b0cbce8e59b7542200107e1fcda8f2f5462671898 30879a2d6d9493eec48c918ec35e855eb7381ee060a09b38e429c221d489cd97c23c37031b96 ad8d633e2c6b0d95f2bf ``` ### bad-magic magic is not 'SMOL' (§5.1) `envelope` ``` 584d4f4c01da6f2bc263adece0989fa5c85785d11aa8baf822f01db3f1149416eaf1465292c3 06fb0ef2bf8b7f93bad98155fa37daec74db0c4cbeda6c6f1dba9d3655825293a846f5413d3a 945f8aa55bdc4f0fffd51e4f59624b753b1691571500e2db82aa003ffedd16ca5125e2abdfc4 dc05c7c76b3d13e7aaee7c7d9eb6702bb90b0cbce8e59b7542200107e1fcda8f2f5462671898 30879a2d6d9493eec48c918ec35e855eb7381ee060a09b38e429c221d489cd97c23c37031b96 ad8d633e2c6b0d95f2bf ``` - `rejected_with`: `SmolError: not a smolmail envelope` ### bad-envelope-version unknown envelope version; the sealed-box construction may differ `envelope` ``` 534d4f4c02da6f2bc263adece0989fa5c85785d11aa8baf822f01db3f1149416eaf1465292c3 06fb0ef2bf8b7f93bad98155fa37daec74db0c4cbeda6c6f1dba9d3655825293a846f5413d3a 945f8aa55bdc4f0fffd51e4f59624b753b1691571500e2db82aa003ffedd16ca5125e2abdfc4 dc05c7c76b3d13e7aaee7c7d9eb6702bb90b0cbce8e59b7542200107e1fcda8f2f5462671898 30879a2d6d9493eec48c918ec35e855eb7381ee060a09b38e429c221d489cd97c23c37031b96 ad8d633e2c6b0d95f2bf ``` - `rejected_with`: `SmolError: unsupported envelope version 2` ### truncated shorter than the 69-byte header plus a 16-byte tag - `envelope`: `534d4f4c01da6f2bc263adece0989fa5c85785d11aa8baf822f01db3f1149416eaf1465292c306fb0ef2bf8b7f93bad98155fa37daec74db0c4cbeda6c6f1dba9d36558252` - `rejected_with`: `SmolError: envelope too short` ### tag-flipped the Poly1305 tag no longer authenticates `envelope` ``` 534d4f4c01da6f2bc263adece0989fa5c85785d11aa8baf822f01db3f1149416eaf1465292c3 06fb0ef2bf8b7f93bad98155fa37daec74db0c4cbeda6c6f1dba9d3655825293a846f5413d3a 945f8aa55bdc4f0fffd51e4f59624b753b1691571500e2db82aa003ffedd16ca5125e2abdfc4 dc05c7c76b3d13e7aaee7c7d9eb6702bb90b0cbce8e59b7542200107e1fcda8f2f5462671898 30879a2d6d9493eec48c918ec35e855eb7381ee060a09b38e429c221d489cd97c23c37031b96 ad8d633e2c6b0d95f2be ``` - `rejected_with`: `SmolError: decryption failed: wrong key or corrupt envelope` ### aad-tampered epk is covered by the AAD, so altering it breaks the tag rather than silently re-addressing the message `envelope` ``` 534d4f4c01da6f2bc263adece0989fa5c85785d11aa8baf822f01db3f1149416eaf1465292c3 06fb0ff2bf8b7f93bad98155fa37daec74db0c4cbeda6c6f1dba9d3655825293a846f5413d3a 945f8aa55bdc4f0fffd51e4f59624b753b1691571500e2db82aa003ffedd16ca5125e2abdfc4 dc05c7c76b3d13e7aaee7c7d9eb6702bb90b0cbce8e59b7542200107e1fcda8f2f5462671898 30879a2d6d9493eec48c918ec35e855eb7381ee060a09b38e429c221d489cd97c23c37031b96 ad8d633e2c6b0d95f2bf ``` - `rejected_with`: `SmolError: decryption failed: wrong key or corrupt envelope` ### not-for-us `to` names a key we do not hold; a client MUST check it against its own `envelope` ``` 534d4f4c0137b39278f08beadeecc5961640eb7634bd664f12ed40c3d69482045607c9471cc3 06fb0ef2bf8b7f93bad98155fa37daec74db0c4cbeda6c6f1dba9d3655825293a846f5413d3a 945f8aa55bdc4f0fffd51e4f59624b753b1691571500e2db82aa003ffedd16ca5125e2abdfc4 dc05c7c76b3d13e7aaee7c7d9eb6702bb90b0cbce8e59b7542200107e1fcda8f2f5462671898 30879a2d6d9493eec48c918ec35e855eb7381ee060a09b38e429c221d489cd97c23c37031b96 ad8d633e2c6b0d95f2bf ``` - `rejected_with`: `SmolError: addressed to g6zze6hqrpvn53gf…, not one of our keys` ### bad-signature decrypts cleanly and the signature is zeroed. An implementation that skips §5.3 verification will accept forged mail here. `envelope` ``` 534d4f4c01da6f2bc263adece0989fa5c85785d11aa8baf822f01db3f1149416eaf1465292c3 06fb0ef2bf8b7f93bad98155fa37daec74db0c4cbeda6c6f1dba9d3655825293a846f5413d3a 945f8aa55bdc4f0fffd51e4f59624b753b1691571500e2db82aa003ffedd16ca5125e2abdfc4 dc05c7c76b3daf229b9065119b10570cbeec2967e78dc7d26906bda10ec4702b50a7d0f93418 a97ab7aa5b6d10455d6ba65081e74824e96e1d637a4dc26845810958fe11269209adcd49b5e7 6471b2c4df881338ba42 ``` - `rejected_with`: `SmolError: signature does not verify` ### signature-bound-to-other-recipient a payload signed for bob, resealed to alice. The signature covers `to`, so re-addressing a recorded message must not verify. `envelope` ``` 534d4f4c01da6f2bc263adece0989fa5c85785d11aa8baf822f01db3f1149416eaf1465292c3 06fb0ef2bf8b7f93bad98155fa37daec74db0c4cbeda6c6f1dba9d3655825293a846f5413d3a 945f8aa55bdc4f0fffd51e4f59624b753b1691571500e2db82aa003ffedd16ca5125e2abdfc4 dc05c7c76b3db7459221085c65f94569e41f2a7f00d84dc2045e491c300ebdfa3f8ea2af2560 1ad057d0013ef1fad9564dc1f24b034f4ebff12458d979f593fe9fa4d5a70595bf0215f69abc 1e1197d0b5979071727f ``` - `rejected_with`: `SmolError: signature does not verify` ### body-len-overflows body_len exceeds the payload (§5.3) `envelope` ``` 534d4f4c01da6f2bc263adece0989fa5c85785d11aa8baf822f01db3f1149416eaf1465292c3 06fb0ef2bf8b7f93bad98155fa37daec74db0c4cbeda6c6f1dba9d3655825293a846f5413d3a 945f8aa55bdc4f0fffd51e4f59624b753b1691571500e2db82aa003ffedd16ca5125e2bbdfc2 dc05c7c76b3d13e7aaee7c7d9eb6702bb90b0cbce8e59b7542200107e1fcda8f2f5462671898 30879a2d6d9493eec48c918ec35e855eb7381ee060a09b38e429c221d489cd977b2479cfcb4d 3883cf888582df8b22f0 ``` - `rejected_with`: `SmolError: payload body length exceeds the payload` ### payload-version unknown payload version `envelope` ``` 534d4f4c01da6f2bc263adece0989fa5c85785d11aa8baf822f01db3f1149416eaf1465292c3 06fb0ef2bf8b7f93bad98155fa37daec74db0c4cbeda6c6f1dba9d3655825290a846f5413d3a 945f8aa55bdc4f0fffd51e4f59624b753b1691571500e2db82aa003ffedd16ca5125e2abdfc4 dc05c7c76b3d13e7aaee7c7d9eb6702bb90b0cbce8e59b7542200107e1fcda8f2f5462671898 30879a2d6d9493eec48c918ec35e855eb7381ee060a09b38e429c221d489cd97372cf15fd0d6 c068a477ac4c35c10862 ``` - `rejected_with`: `SmolError: unsupported payload version` ### dated-in-the-future time is 4102444800, more than 86400s ahead of any clock before 2100 (§5.3) `envelope` ``` 534d4f4c01da6f2bc263adece0989fa5c85785d11aa8baf822f01db3f1149416eaf1465292c3 06fb0ef2bf8b7f93bad98155fa37daec74db0c4cbeda6c6f1dba9d3655825293a846f5413d3a 945f8aa55bdc4f0fffd51e4f59624b753b1691571500e2db82aa003ffedd8b19bf25e2abdfc4 c605dfcb7d3da3c142dc7b0dbabf90b361744b6247bb8e9fc9407d51b383f018556d9fbfd999 beaeb49bec2d719ce3c62785f850ce261eb68784050fd68f1e7655fcae4a659fe7353abcadb4 da68e9b733c5704cbb51 ``` - `rejected_with`: `SmolError: payload is dated in the future` ### low-order-epk a low-order ephemeral key, which §2 requires be refused `envelope` ``` 534d4f4c01da6f2bc263adece0989fa5c85785d11aa8baf822f01db3f1149416eaf1465292e0 eb7a7c3b41b8ae1656e3faf19fc46ada098deb9c32b1fd866205165f49b80093a846f5413d3a 945f8aa55bdc4f0fffd51e4f59624b753b1691571500e2db82aa003ffedd16ca5125e2abdfc4 dc05c7c76b3d13e7aaee7c7d9eb6702bb90b0cbce8e59b7542200107e1fcda8f2f5462671898 30879a2d6d9493eec48c918ec35e855eb7381ee060a09b38e429c221d489cd97c23c37031b96 ad8d633e2c6b0d95f2bf ``` - `rejected_with`: `SmolError: rejected key agreement: Unexpected library error` ### Low-order X25519 keys §2 and §4: a received ephemeral public key that is a low-order point MUST be refused, and an all-zero X25519 output MUST be refused. libsodium reports the first as the second, since the agreement output is zero. - `0000000000000000000000000000000000000000000000000000000000000000` - `0100000000000000000000000000000000000000000000000000000000000000` - `e0eb7a7c3b41b8ae1656e3faf19fc46ada098deb9c32b1fd866205165f49b800` - `5f9c95bca3508c24b1d0b1559c83ef5b04445cc4581c8e86d8224eddd09f1157` - `ecffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f` - `edffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f` - `eeffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7f` ### Invalid identity keys Keys that do not decode as Ed25519 points, or are of small order, so §2's map to X25519 has no valid result. - `0000000000000000000000000000000000000000000000000000000000000000` — SmolError: not a valid Ed25519 public key: Unexpected library error - `ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff` — SmolError: not a valid Ed25519 public key: Unexpected library error - `0100000000000000000000000000000000000000000000000000000000000000` — SmolError: not a valid Ed25519 public key: Unexpected library error ## License These vectors are licensed under [CC BY-SA 4.0](LICENSES/CC-BY-SA-4.0.txt), with the specification.