@@ -6,8 +6,10 @@ use super::*;
66use crate :: chat:: { CantSendReason , add_contact_to_chat, remove_contact_from_chat} ;
77use crate :: chatlist:: Chatlist ;
88use crate :: constants:: Chattype ;
9+ use crate :: constants:: DC_CHAT_ID_TRASH ;
910use crate :: key:: self_fingerprint;
1011use crate :: mimeparser:: { GossipedKey , SystemMessage } ;
12+ use crate :: qr:: Qr ;
1113use crate :: receive_imf:: receive_imf;
1214use crate :: stock_str:: { self , messages_e2e_encrypted} ;
1315use crate :: test_utils:: {
@@ -1253,3 +1255,118 @@ async fn test_user_deletes_chat_before_securejoin_completes() -> Result<()> {
12531255
12541256 Ok ( ( ) )
12551257}
1258+
1259+ /// Tests that vc-request is processed even if the server
1260+ /// encrypts incoming unencrypted messages with OpenPGP.
1261+ ///
1262+ /// For an example of software that encrypts incoming messages
1263+ /// with OpenPGP, see <https://lacre.io/>.
1264+ #[ tokio:: test( flavor = "multi_thread" , worker_threads = 2 ) ]
1265+ async fn test_vc_request_encrypted_at_rest ( ) -> Result < ( ) > {
1266+ let mut tcm = TestContextManager :: new ( ) ;
1267+ let alice = & tcm. alice ( ) . await ;
1268+ let bob = & tcm. bob ( ) . await ;
1269+
1270+ let qr = get_securejoin_qr ( alice, None ) . await ?;
1271+
1272+ let Qr :: AskVerifyContact { invitenumber, .. } = check_qr ( bob, & qr) . await ? else {
1273+ panic ! ( "Failed to parse QR code" ) ;
1274+ } ;
1275+
1276+ // Encrypted payload is this message encrypted to Alice's key:
1277+ /*
1278+ Content-Type: multipart/mixed;
1279+ boundary="1888168c99b6020b_ed9b3571859a92d7_eeabe50050fc923b"
1280+
1281+ --1888168c99b6020b_ed9b3571859a92d7_eeabe50050fc923b
1282+ Content-Type: text/plain; charset="utf-8"
1283+ Message-ID: <4f108a03-6c03-4f41-a6fb-fcd05b94c21f@localhost>
1284+ Content-Transfer-Encoding: 7bit
1285+
1286+ Secure-Join: vc-request
1287+ --1888168c99b6020b_ed9b3571859a92d7_eeabe50050fc923b--
1288+ */
1289+
1290+ let payload = format ! ( "To: <alice@example.org>
1291+ Subject: [...]
1292+ Date: Tue, 6 Jan 2026 08:20:47 +0000
1293+ References: <4f108a03-6c03-4f41-a6fb-fcd05b94c21f@localhost>
1294+ Chat-Version: 1.0
1295+ Autocrypt: addr=bob@example.net; prefer-encrypt=mutual; keydata=xsBNBF4wx1cBCADOwLS/xCd8iKDWUsyTfVzWby+ZGKPpamPTvdj0GFgnf0B1EBaA5//PjA
1296+ zbK5iKio6QNEmZagzJPkXPByJcAIRUm0T16tqDtCvxm+H93YEXpHi/XWOeJw9kohATSqUtsRO0pFJe
1297+ DvPiMTmQrEmHYoWDSQBfCrowZdvnMAlbJ9JjYOngcMeTxc0jxmPs5s17yFC+1OWu4fwWCyUM3wy1Jz
1298+ dKTcDWryrSkvmgFdUqJ7pJDk1HFTt+x9tvQlK3un9BXiRwv0u0zDSuI8eDH/dRLA4UL9Pq6vmJmBam
1299+ e1BPsE1PA7VzeTSJR2ooJXMT6o2AmH8PPUfRkv3OiWuh7LM5FSpHABEBAAHNETxib2JAZXhhbXBsZS
1300+ 5uZXQ+wsCOBBMBCAA4BQJpXW0wFiEEzMtaqfbhFByUMWXx2xixjLz3BIcCGwMCHgAECwkIBwYVCAkK
1301+ CwIDFgIBAScCGQEACgkQ2xixjLz3BIcexwgAsOauz2xZ6QhVBQNX3Hg8OoYTn60w6b4XUOpI4UtqAT
1302+ bAmPr5VPhCUa5vzI19QCSekLZIVxUSl6C+7YF/mU8yJldKPgq1Kpr8tbnISNbUDpvuGz7NQdK0TEwx
1303+ RkPDw+ilqY7v2Rhhg0Sogi23Yrbyqvs72oorDjia6dBA7VLixpW1O9h/MfQ6WiXJcHSavoLqk2hFW1
1304+ y/AsVmArGiuT+kzRJWhTzojZLjQLHTKQii/AOQ3MhkJycyayI/igSEDWWwCcuqL8SF+PUJWGyU5PxU
1305+ 2hTHDBsVItLLsqseM3WrwJRkBBdsdsR8+moHVyXJV9Gfl/4UFQCgltdEwWISgNTbAc7ATQReMMdXAQ
1306+ gAogeBLbIjaeJII3W2pxsu+SEusQkJVykbGYDtqyXV+XBZisY4GE0kTawK5mqSh+rDqquCxDgYWBRT
1307+ nGZwEKohnj2NG75pjfyVPhYMUdJt7+Ya1oiFvZlgrrOj1btjevq53yFtQolMN+X2oS8mlf9jSzIyPC
1308+ eDxJk1N1gxaAATg3ByAyB1Td0wDdFPp48ni8qzfyGZeYicvJlx74YnOaja2lnI/y+I9LsmmqiOgI8H
1309+ cbmH1od5qSnVjhcpBoTEA15YLIEkSE3C00Q5USlDS3EVg/IOu3FXnLl7v0hQ/jXyv88eycfpSfFcbM
1310+ Hot9VtJ4TIPIoSX7DQ+uU2SXJKiZNkVQARAQABwsB2BBgBCAAgBQJpXW0wAhsMFiEEzMtaqfbhFByU
1311+ MWXx2xixjLz3BIcACgkQ2xixjLz3BIcxvwf9G33yLtvekpNGeRbWkjRXSa083k/4CZpkF0Fb5led1O
1312+ hjRjw9KQdZj68qn1vVrDxygnYdHwZWy8WbwEkK+l3gyJ2v2D/Wsj+sHjQ1YMtPnx+EsRFWjKsolYfN
1313+ gJZ+IfMTasip8uJNxN5LIvI/svn43mzgeLUudddekmr/2eekhXfYz5covje3yf+u4rYDWQ78TLpJL5
1314+ bxTwiiUyV1ZIO1G2F4RNjv8wZHsGD3DasQck+OCV7jQNuyojcmq6J22lXN0clisI51mHzwkLAnI+Yh
1315+ jRj3nqwVSCxsmgfejap53JGHEL0CEy6KvepLqjFf8BiK4kwRBmI7/YWOyY2xBWdTew==
1316+ Secure-Join: vc-request
1317+ Secure-Join-Invitenumber: {invitenumber}
1318+ MIME-Version: 1.0
1319+ From: <bob@example.net>
1320+ Message-ID: <4f108a03-6c03-4f41-a6fb-fcd05b94c21f@localhost>
1321+ Content-Type: multipart/encrypted;
1322+ protocol=\" application/pgp-encrypted\" ;
1323+ boundary=\" 1767687657/562150/131174/example.org\"
1324+
1325+ This is a MIME-encapsulated message.
1326+
1327+ --1767687657/562150/131174/example.org
1328+ Content-Type: application/pgp-encrypted
1329+ Content-Disposition: attachment
1330+
1331+ Version: 1
1332+
1333+ --1767687657/562150/131174/example.org
1334+ Content-Type: application/octet-stream
1335+ Content-Disposition: inline; filename=\" msg.asc\"
1336+
1337+ -----BEGIN PGP MESSAGE-----
1338+
1339+ wV4D5tq63hTeebASAQdAGKP3GqsznPOYBXOo8FYf5x8r0ZaJZUGkXIR+Oi32H1Mw
1340+ LdVEu0jcXmZ1fGZ7LLPtvfwllB2W9Bhiy/lCZZs+c98VYzSWaT0DHmp23WvTsBZn
1341+ 0sDeAS0n2I6xPwYhUjqL8G1a9xdyvZRgHYUXhiARrXzx7G+aX8/KFjk6e2OZxiVy
1342+ PSHKh61T9wPYzPMlToPsI0GjXAzOgI9I3XQ8xPqihiUpnU6BSg+Tj26m9ZqdJe8v
1343+ aVAHxAu7aqz7eljp2H336Idgfvf1lXdA6gMA8HhHI729Ws/Mc8lcgefM9kzZWEIN
1344+ FOBYmf4JCdTghESpEJ5i+pF28ChqZ3+8lGzNmT66c2SQRTclwxFa4SS19D4mxkHq
1345+ iOMqj7LZ8R6IhnNVRD1V4mVapc7vFVZy8ViyZlmhJF0TBR/TEXlit6vtSkDKFiR9
1346+ Tb5zuFQVAwhun3i1tG3/Ii1ReflZNnteVlL1J1XnptOJ70vVUeO3qRqkbkiH8Mdm
1347+ Asvy24WKkz9jmEgdt0Hj8VUHtcOL5xmtsr0ZUCLUriylpzDh8E+0LTl2/DOgH+mI
1348+ D/gFLCzFHjI0jfXyLTGCYOPYAnvqJukLBT/X7JbCAI/62aq0K28Lp6beJhFs+bIz
1349+ gU6dGXsFMe/RpRHrIAkMAaM5xkxMDRuRJDxiUdS/X+Y8
1350+ =QrdS
1351+ -----END PGP MESSAGE-----
1352+
1353+ --1767687657/562150/131174/example.org--
1354+ " ) ;
1355+
1356+ // Alice receives vc-request, but it is encrypted
1357+ // by the server.
1358+ let received = receive_imf ( alice, payload. as_bytes ( ) , false )
1359+ . await ?
1360+ . unwrap ( ) ;
1361+ assert_eq ! ( received. chat_id, DC_CHAT_ID_TRASH ) ;
1362+
1363+ // Test that Alice sends vc-auth-required after processing vc-request.
1364+ let sent = alice. pop_sent_msg ( ) . await ;
1365+ let msg = bob. parse_msg ( & sent) . await ;
1366+ assert_eq ! (
1367+ msg. get_header( HeaderDef :: SecureJoin ) . unwrap( ) ,
1368+ "vc-auth-required"
1369+ ) ;
1370+
1371+ Ok ( ( ) )
1372+ }
0 commit comments