+3397
-104
Diff
round #0
+12
.sqlx/query-0295414146e4ddacad638486443fd1036609ab8443390820be8696f708be3812.json
+12
.sqlx/query-0295414146e4ddacad638486443fd1036609ab8443390820be8696f708be3812.json
+18
.sqlx/query-0a3eaf432e99ef22aa6b3b43978740b085f6416a058ea2da6d639ea1cf276eda.json
+18
.sqlx/query-0a3eaf432e99ef22aa6b3b43978740b085f6416a058ea2da6d639ea1cf276eda.json
···
1
+
{
2
+
"db_name": "PostgreSQL",
3
+
"query": "INSERT INTO signal_sender_keys\n (address, device_id, identity, distribution_id, record)\n VALUES ($1, $2, $3, $4, $5)\n ON CONFLICT (address, device_id, identity, distribution_id) DO UPDATE SET record = $5",
4
+
"describe": {
5
+
"columns": [],
6
+
"parameters": {
7
+
"Left": [
8
+
"Text",
9
+
"Int4",
10
+
"Text",
11
+
"Uuid",
12
+
"Bytea"
13
+
]
14
+
},
15
+
"nullable": []
16
+
},
17
+
"hash": "0a3eaf432e99ef22aa6b3b43978740b085f6416a058ea2da6d639ea1cf276eda"
18
+
}
+12
.sqlx/query-166ee5a554e3ddc75496616d9fba75a15cc0c072f493f579b881a4f2300f38c8.json
+12
.sqlx/query-166ee5a554e3ddc75496616d9fba75a15cc0c072f493f579b881a4f2300f38c8.json
+23
.sqlx/query-1a061c261518573c29aa55c5d8e2181f1728034e723ed0bc836e928b4c69128f.json
+23
.sqlx/query-1a061c261518573c29aa55c5d8e2181f1728034e723ed0bc836e928b4c69128f.json
···
1
+
{
2
+
"db_name": "PostgreSQL",
3
+
"query": "SELECT record FROM signal_signed_pre_keys WHERE id = $1 AND identity = $2",
4
+
"describe": {
5
+
"columns": [
6
+
{
7
+
"ordinal": 0,
8
+
"name": "record",
9
+
"type_info": "Bytea"
10
+
}
11
+
],
12
+
"parameters": {
13
+
"Left": [
14
+
"Int4",
15
+
"Text"
16
+
]
17
+
},
18
+
"nullable": [
19
+
false
20
+
]
21
+
},
22
+
"hash": "1a061c261518573c29aa55c5d8e2181f1728034e723ed0bc836e928b4c69128f"
23
+
}
+23
.sqlx/query-1aac5ab7dbc29f0d0937767ae174e8b47d236b3cdc973974cec413dc65198d64.json
+23
.sqlx/query-1aac5ab7dbc29f0d0937767ae174e8b47d236b3cdc973974cec413dc65198d64.json
···
1
+
{
2
+
"db_name": "PostgreSQL",
3
+
"query": "SELECT record FROM signal_kyber_pre_keys WHERE id = $1 AND identity = $2",
4
+
"describe": {
5
+
"columns": [
6
+
{
7
+
"ordinal": 0,
8
+
"name": "record",
9
+
"type_info": "Bytea"
10
+
}
11
+
],
12
+
"parameters": {
13
+
"Left": [
14
+
"Int4",
15
+
"Text"
16
+
]
17
+
},
18
+
"nullable": [
19
+
false
20
+
]
21
+
},
22
+
"hash": "1aac5ab7dbc29f0d0937767ae174e8b47d236b3cdc973974cec413dc65198d64"
23
+
}
+16
.sqlx/query-1d4459863eeddea9ccb5ce5c0eaffd39d56a763728ce5b1f76871265e704e241.json
+16
.sqlx/query-1d4459863eeddea9ccb5ce5c0eaffd39d56a763728ce5b1f76871265e704e241.json
···
1
+
{
2
+
"db_name": "PostgreSQL",
3
+
"query": "INSERT INTO signal_kyber_pre_keys (id, identity, record, is_last_resort)\n VALUES ($1, $2, $3, FALSE)\n ON CONFLICT (id, identity) DO UPDATE SET record = $3, is_last_resort = FALSE",
4
+
"describe": {
5
+
"columns": [],
6
+
"parameters": {
7
+
"Left": [
8
+
"Int4",
9
+
"Text",
10
+
"Bytea"
11
+
]
12
+
},
13
+
"nullable": []
14
+
},
15
+
"hash": "1d4459863eeddea9ccb5ce5c0eaffd39d56a763728ce5b1f76871265e704e241"
16
+
}
+15
.sqlx/query-1f464d947e93274cbc974f8a6f31d8a47eb676df857fa83f08ed1937cf8a6d9d.json
+15
.sqlx/query-1f464d947e93274cbc974f8a6f31d8a47eb676df857fa83f08ed1937cf8a6d9d.json
···
1
+
{
2
+
"db_name": "PostgreSQL",
3
+
"query": "DELETE FROM signal_sessions WHERE address = $1 AND identity = $2",
4
+
"describe": {
5
+
"columns": [],
6
+
"parameters": {
7
+
"Left": [
8
+
"Text",
9
+
"Text"
10
+
]
11
+
},
12
+
"nullable": []
13
+
},
14
+
"hash": "1f464d947e93274cbc974f8a6f31d8a47eb676df857fa83f08ed1937cf8a6d9d"
15
+
}
+12
.sqlx/query-222836500a964ee6fd238ddb128691215cd15d2ede9a1a19e7a580e4d6644ce8.json
+12
.sqlx/query-222836500a964ee6fd238ddb128691215cd15d2ede9a1a19e7a580e4d6644ce8.json
+12
.sqlx/query-252d42bb50ef918fe414d036979daba055dbadd3cd7e1bdcce4526867be79930.json
+12
.sqlx/query-252d42bb50ef918fe414d036979daba055dbadd3cd7e1bdcce4526867be79930.json
+15
.sqlx/query-29c834b7870cdbcdcc2d2c9259a04326e20433237ebe25e33dbd39952ae9f976.json
+15
.sqlx/query-29c834b7870cdbcdcc2d2c9259a04326e20433237ebe25e33dbd39952ae9f976.json
···
1
+
{
2
+
"db_name": "PostgreSQL",
3
+
"query": "INSERT INTO signal_kv (key, value) VALUES ($1, $2)\n ON CONFLICT (key) DO UPDATE SET value = $2",
4
+
"describe": {
5
+
"columns": [],
6
+
"parameters": {
7
+
"Left": [
8
+
"Text",
9
+
"Bytea"
10
+
]
11
+
},
12
+
"nullable": []
13
+
},
14
+
"hash": "29c834b7870cdbcdcc2d2c9259a04326e20433237ebe25e33dbd39952ae9f976"
15
+
}
+17
.sqlx/query-31edfe22cdd8e5f62322dad01a65165ec9546eaa92c9e372a5a4fce99d938d22.json
+17
.sqlx/query-31edfe22cdd8e5f62322dad01a65165ec9546eaa92c9e372a5a4fce99d938d22.json
···
1
+
{
2
+
"db_name": "PostgreSQL",
3
+
"query": "INSERT INTO signal_base_keys_seen\n (kyber_pre_key_id, signed_pre_key_id, identity, base_key)\n VALUES ($1, $2, $3, $4)",
4
+
"describe": {
5
+
"columns": [],
6
+
"parameters": {
7
+
"Left": [
8
+
"Int4",
9
+
"Int4",
10
+
"Text",
11
+
"Bytea"
12
+
]
13
+
},
14
+
"nullable": []
15
+
},
16
+
"hash": "31edfe22cdd8e5f62322dad01a65165ec9546eaa92c9e372a5a4fce99d938d22"
17
+
}
+12
.sqlx/query-374be0bd97ed927b15929e2f86d88913b2fec45ab67e4805fb9f1e39b422ee7f.json
+12
.sqlx/query-374be0bd97ed927b15929e2f86d88913b2fec45ab67e4805fb9f1e39b422ee7f.json
+15
.sqlx/query-3a3eee11be6a9c5fe012d2a634c7ef514fb695ca6a4ba7631d1c5aba87a854a5.json
+15
.sqlx/query-3a3eee11be6a9c5fe012d2a634c7ef514fb695ca6a4ba7631d1c5aba87a854a5.json
···
1
+
{
2
+
"db_name": "PostgreSQL",
3
+
"query": "DELETE FROM signal_pre_keys WHERE id = $1 AND identity = $2",
4
+
"describe": {
5
+
"columns": [],
6
+
"parameters": {
7
+
"Left": [
8
+
"Int4",
9
+
"Text"
10
+
]
11
+
},
12
+
"nullable": []
13
+
},
14
+
"hash": "3a3eee11be6a9c5fe012d2a634c7ef514fb695ca6a4ba7631d1c5aba87a854a5"
15
+
}
+12
.sqlx/query-4011d789a6b619231f4e2b917753f0b4452f21243e1d95d47dbaa91cac019e64.json
+12
.sqlx/query-4011d789a6b619231f4e2b917753f0b4452f21243e1d95d47dbaa91cac019e64.json
+22
.sqlx/query-4316de453ec1d5ba65a1dbee29599287d42bf87517936b3b61958c0675ce8115.json
+22
.sqlx/query-4316de453ec1d5ba65a1dbee29599287d42bf87517936b3b61958c0675ce8115.json
···
1
+
{
2
+
"db_name": "PostgreSQL",
3
+
"query": "SELECT value FROM signal_kv WHERE key = $1",
4
+
"describe": {
5
+
"columns": [
6
+
{
7
+
"ordinal": 0,
8
+
"name": "value",
9
+
"type_info": "Bytea"
10
+
}
11
+
],
12
+
"parameters": {
13
+
"Left": [
14
+
"Text"
15
+
]
16
+
},
17
+
"nullable": [
18
+
false
19
+
]
20
+
},
21
+
"hash": "4316de453ec1d5ba65a1dbee29599287d42bf87517936b3b61958c0675ce8115"
22
+
}
+12
.sqlx/query-43583f8246016d15d9875c4d33855317c41ae07af5676228c0533724590ec6ed.json
+12
.sqlx/query-43583f8246016d15d9875c4d33855317c41ae07af5676228c0533724590ec6ed.json
+23
.sqlx/query-4bcd896340fc9178e2d97ad572269e8f57561190ec5f94ccfa06ca93f4827e79.json
+23
.sqlx/query-4bcd896340fc9178e2d97ad572269e8f57561190ec5f94ccfa06ca93f4827e79.json
···
1
+
{
2
+
"db_name": "PostgreSQL",
3
+
"query": "SELECT record FROM signal_identities WHERE address = $1 AND identity = $2",
4
+
"describe": {
5
+
"columns": [
6
+
{
7
+
"ordinal": 0,
8
+
"name": "record",
9
+
"type_info": "Bytea"
10
+
}
11
+
],
12
+
"parameters": {
13
+
"Left": [
14
+
"Text",
15
+
"Text"
16
+
]
17
+
},
18
+
"nullable": [
19
+
false
20
+
]
21
+
},
22
+
"hash": "4bcd896340fc9178e2d97ad572269e8f57561190ec5f94ccfa06ca93f4827e79"
23
+
}
+17
.sqlx/query-4d22ba21356bdc84ea549799c77cab8c34ca9a5f0815150254b590fd87509eb8.json
+17
.sqlx/query-4d22ba21356bdc84ea549799c77cab8c34ca9a5f0815150254b590fd87509eb8.json
···
1
+
{
2
+
"db_name": "PostgreSQL",
3
+
"query": "INSERT INTO signal_sessions (address, device_id, identity, record)\n VALUES ($1, $2, $3, $4)\n ON CONFLICT (address, device_id, identity) DO UPDATE SET record = $4",
4
+
"describe": {
5
+
"columns": [],
6
+
"parameters": {
7
+
"Left": [
8
+
"Text",
9
+
"Int4",
10
+
"Text",
11
+
"Bytea"
12
+
]
13
+
},
14
+
"nullable": []
15
+
},
16
+
"hash": "4d22ba21356bdc84ea549799c77cab8c34ca9a5f0815150254b590fd87509eb8"
17
+
}
+23
.sqlx/query-513a0d3b907df1004f2178ebf14fc182f20fc13c5691cbeb7656d428cb6437f9.json
+23
.sqlx/query-513a0d3b907df1004f2178ebf14fc182f20fc13c5691cbeb7656d428cb6437f9.json
···
1
+
{
2
+
"db_name": "PostgreSQL",
3
+
"query": "SELECT is_last_resort FROM signal_kyber_pre_keys WHERE id = $1 AND identity = $2",
4
+
"describe": {
5
+
"columns": [
6
+
{
7
+
"ordinal": 0,
8
+
"name": "is_last_resort",
9
+
"type_info": "Bool"
10
+
}
11
+
],
12
+
"parameters": {
13
+
"Left": [
14
+
"Int4",
15
+
"Text"
16
+
]
17
+
},
18
+
"nullable": [
19
+
false
20
+
]
21
+
},
22
+
"hash": "513a0d3b907df1004f2178ebf14fc182f20fc13c5691cbeb7656d428cb6437f9"
23
+
}
+14
.sqlx/query-53814b5db4f051c30573d146007ddc487f4c12c726bb970efe17e325536629e4.json
+14
.sqlx/query-53814b5db4f051c30573d146007ddc487f4c12c726bb970efe17e325536629e4.json
···
1
+
{
2
+
"db_name": "PostgreSQL",
3
+
"query": "INSERT INTO signal_kv (key, value) VALUES ('master_key', $1)\n ON CONFLICT (key) DO UPDATE SET value = $1",
4
+
"describe": {
5
+
"columns": [],
6
+
"parameters": {
7
+
"Left": [
8
+
"Bytea"
9
+
]
10
+
},
11
+
"nullable": []
12
+
},
13
+
"hash": "53814b5db4f051c30573d146007ddc487f4c12c726bb970efe17e325536629e4"
14
+
}
+14
.sqlx/query-5cd556968671fc8ecf57dd7fd40f65e3a168f17bd389ce2cf7ddee27d810cf1d.json
+14
.sqlx/query-5cd556968671fc8ecf57dd7fd40f65e3a168f17bd389ce2cf7ddee27d810cf1d.json
···
1
+
{
2
+
"db_name": "PostgreSQL",
3
+
"query": "INSERT INTO signal_kv (key, value) VALUES ('sender_certificate', $1)\n ON CONFLICT (key) DO UPDATE SET value = $1",
4
+
"describe": {
5
+
"columns": [],
6
+
"parameters": {
7
+
"Left": [
8
+
"Bytea"
9
+
]
10
+
},
11
+
"nullable": []
12
+
},
13
+
"hash": "5cd556968671fc8ecf57dd7fd40f65e3a168f17bd389ce2cf7ddee27d810cf1d"
14
+
}
+16
.sqlx/query-62dc57cf7ad007a6458df06619fe7e0bf5ffeba195e55793f6bf6d170e053226.json
+16
.sqlx/query-62dc57cf7ad007a6458df06619fe7e0bf5ffeba195e55793f6bf6d170e053226.json
···
1
+
{
2
+
"db_name": "PostgreSQL",
3
+
"query": "INSERT INTO signal_identities (address, identity, record)\n VALUES ($1, $2, $3)\n ON CONFLICT (address, identity) DO UPDATE SET record = $3",
4
+
"describe": {
5
+
"columns": [],
6
+
"parameters": {
7
+
"Left": [
8
+
"Text",
9
+
"Text",
10
+
"Bytea"
11
+
]
12
+
},
13
+
"nullable": []
14
+
},
15
+
"hash": "62dc57cf7ad007a6458df06619fe7e0bf5ffeba195e55793f6bf6d170e053226"
16
+
}
+23
.sqlx/query-63ecf786e52a52d83232f6d4c8d93d5d7065f5dbfd3cd1e259d7990d02da1114.json
+23
.sqlx/query-63ecf786e52a52d83232f6d4c8d93d5d7065f5dbfd3cd1e259d7990d02da1114.json
···
1
+
{
2
+
"db_name": "PostgreSQL",
3
+
"query": "SELECT COUNT(*) AS \"count!\" FROM signal_kyber_pre_keys\n WHERE identity = $1 AND is_last_resort = $2",
4
+
"describe": {
5
+
"columns": [
6
+
{
7
+
"ordinal": 0,
8
+
"name": "count!",
9
+
"type_info": "Int8"
10
+
}
11
+
],
12
+
"parameters": {
13
+
"Left": [
14
+
"Text",
15
+
"Bool"
16
+
]
17
+
},
18
+
"nullable": [
19
+
null
20
+
]
21
+
},
22
+
"hash": "63ecf786e52a52d83232f6d4c8d93d5d7065f5dbfd3cd1e259d7990d02da1114"
23
+
}
+22
.sqlx/query-6a91d97ed4f955ce0936eced6318c630f39ebebc52cee584f1b0dacefec984cd.json
+22
.sqlx/query-6a91d97ed4f955ce0936eced6318c630f39ebebc52cee584f1b0dacefec984cd.json
···
1
+
{
2
+
"db_name": "PostgreSQL",
3
+
"query": "SELECT record FROM signal_kyber_pre_keys\n WHERE identity = $1 AND is_last_resort = TRUE",
4
+
"describe": {
5
+
"columns": [
6
+
{
7
+
"ordinal": 0,
8
+
"name": "record",
9
+
"type_info": "Bytea"
10
+
}
11
+
],
12
+
"parameters": {
13
+
"Left": [
14
+
"Text"
15
+
]
16
+
},
17
+
"nullable": [
18
+
false
19
+
]
20
+
},
21
+
"hash": "6a91d97ed4f955ce0936eced6318c630f39ebebc52cee584f1b0dacefec984cd"
22
+
}
+12
.sqlx/query-6cb39ddd462ae93fe97d930ce64425ed16271adc4ca066c4d51bb742beffc22b.json
+12
.sqlx/query-6cb39ddd462ae93fe97d930ce64425ed16271adc4ca066c4d51bb742beffc22b.json
+23
.sqlx/query-6cbfcd552a7b4eeb6a1e525f2f11e8f432405e3606e3af7d31b9eca32bc28607.json
+23
.sqlx/query-6cbfcd552a7b4eeb6a1e525f2f11e8f432405e3606e3af7d31b9eca32bc28607.json
···
1
+
{
2
+
"db_name": "PostgreSQL",
3
+
"query": "SELECT record FROM signal_pre_keys WHERE id = $1 AND identity = $2",
4
+
"describe": {
5
+
"columns": [
6
+
{
7
+
"ordinal": 0,
8
+
"name": "record",
9
+
"type_info": "Bytea"
10
+
}
11
+
],
12
+
"parameters": {
13
+
"Left": [
14
+
"Int4",
15
+
"Text"
16
+
]
17
+
},
18
+
"nullable": [
19
+
false
20
+
]
21
+
},
22
+
"hash": "6cbfcd552a7b4eeb6a1e525f2f11e8f432405e3606e3af7d31b9eca32bc28607"
23
+
}
+14
.sqlx/query-6f14e2d74ed0c1e0946c62da2a3ddd63344892bdd4022073123604ee17114ce0.json
+14
.sqlx/query-6f14e2d74ed0c1e0946c62da2a3ddd63344892bdd4022073123604ee17114ce0.json
···
1
+
{
2
+
"db_name": "PostgreSQL",
3
+
"query": "INSERT INTO signal_kv (key, value) VALUES ('registration', $1)\n ON CONFLICT (key) DO UPDATE SET value = $1",
4
+
"describe": {
5
+
"columns": [],
6
+
"parameters": {
7
+
"Left": [
8
+
"Bytea"
9
+
]
10
+
},
11
+
"nullable": []
12
+
},
13
+
"hash": "6f14e2d74ed0c1e0946c62da2a3ddd63344892bdd4022073123604ee17114ce0"
14
+
}
+16
.sqlx/query-811af305fef56437151c1cfe27eaccf6312b8234f1217a81a4d36cd5758fd863.json
+16
.sqlx/query-811af305fef56437151c1cfe27eaccf6312b8234f1217a81a4d36cd5758fd863.json
···
1
+
{
2
+
"db_name": "PostgreSQL",
3
+
"query": "INSERT INTO signal_pre_keys (id, identity, record)\n VALUES ($1, $2, $3)\n ON CONFLICT (id, identity) DO UPDATE SET record = $3",
4
+
"describe": {
5
+
"columns": [],
6
+
"parameters": {
7
+
"Left": [
8
+
"Int4",
9
+
"Text",
10
+
"Bytea"
11
+
]
12
+
},
13
+
"nullable": []
14
+
},
15
+
"hash": "811af305fef56437151c1cfe27eaccf6312b8234f1217a81a4d36cd5758fd863"
16
+
}
+23
.sqlx/query-894169c5a40acade1000869bdde61d09984e17a686c1b487004d79897ecb4e4f.json
+23
.sqlx/query-894169c5a40acade1000869bdde61d09984e17a686c1b487004d79897ecb4e4f.json
···
1
+
{
2
+
"db_name": "PostgreSQL",
3
+
"query": "INSERT INTO signal_profile_keys (uuid, key) VALUES ($1, $2)\n ON CONFLICT (uuid) DO UPDATE SET key = $2\n RETURNING (xmax = 0) AS \"inserted!\"",
4
+
"describe": {
5
+
"columns": [
6
+
{
7
+
"ordinal": 0,
8
+
"name": "inserted!",
9
+
"type_info": "Bool"
10
+
}
11
+
],
12
+
"parameters": {
13
+
"Left": [
14
+
"Uuid",
15
+
"Bytea"
16
+
]
17
+
},
18
+
"nullable": [
19
+
null
20
+
]
21
+
},
22
+
"hash": "894169c5a40acade1000869bdde61d09984e17a686c1b487004d79897ecb4e4f"
23
+
}
+22
.sqlx/query-9da9a790efa51edd6abcb4b0991b307c3ba7f0a929e114a4e0cb2ffb88adfbbb.json
+22
.sqlx/query-9da9a790efa51edd6abcb4b0991b307c3ba7f0a929e114a4e0cb2ffb88adfbbb.json
···
1
+
{
2
+
"db_name": "PostgreSQL",
3
+
"query": "SELECT MAX(id) FROM signal_kyber_pre_keys\n WHERE identity = $1 AND is_last_resort = TRUE",
4
+
"describe": {
5
+
"columns": [
6
+
{
7
+
"ordinal": 0,
8
+
"name": "max",
9
+
"type_info": "Int4"
10
+
}
11
+
],
12
+
"parameters": {
13
+
"Left": [
14
+
"Text"
15
+
]
16
+
},
17
+
"nullable": [
18
+
null
19
+
]
20
+
},
21
+
"hash": "9da9a790efa51edd6abcb4b0991b307c3ba7f0a929e114a4e0cb2ffb88adfbbb"
22
+
}
+24
.sqlx/query-9fdcff515573446f0b4340bf94421bb8a425cc65304fa8c3fd153945904136f0.json
+24
.sqlx/query-9fdcff515573446f0b4340bf94421bb8a425cc65304fa8c3fd153945904136f0.json
···
1
+
{
2
+
"db_name": "PostgreSQL",
3
+
"query": "SELECT device_id FROM signal_sessions\n WHERE address = $1 AND device_id != $2 AND identity = $3",
4
+
"describe": {
5
+
"columns": [
6
+
{
7
+
"ordinal": 0,
8
+
"name": "device_id",
9
+
"type_info": "Int4"
10
+
}
11
+
],
12
+
"parameters": {
13
+
"Left": [
14
+
"Text",
15
+
"Int4",
16
+
"Text"
17
+
]
18
+
},
19
+
"nullable": [
20
+
false
21
+
]
22
+
},
23
+
"hash": "9fdcff515573446f0b4340bf94421bb8a425cc65304fa8c3fd153945904136f0"
24
+
}
+12
.sqlx/query-a403c2982978159b120d4bfa6d6fdca5808b667e54b0765b5ada047ce6dac9d6.json
+12
.sqlx/query-a403c2982978159b120d4bfa6d6fdca5808b667e54b0765b5ada047ce6dac9d6.json
+15
.sqlx/query-adabc98c853ae77678ad6cf1747384706154334cc507eb7542a8b5490f5a1e2a.json
+15
.sqlx/query-adabc98c853ae77678ad6cf1747384706154334cc507eb7542a8b5490f5a1e2a.json
···
1
+
{
2
+
"db_name": "PostgreSQL",
3
+
"query": "UPDATE signal_kyber_pre_keys\n SET stale_at = $1\n WHERE identity = $2 AND is_last_resort = FALSE AND stale_at IS NULL",
4
+
"describe": {
5
+
"columns": [],
6
+
"parameters": {
7
+
"Left": [
8
+
"Timestamptz",
9
+
"Text"
10
+
]
11
+
},
12
+
"nullable": []
13
+
},
14
+
"hash": "adabc98c853ae77678ad6cf1747384706154334cc507eb7542a8b5490f5a1e2a"
15
+
}
+16
.sqlx/query-b157b94e003376d827b92eab1ff55caa773ed5691e2e555ab1d1f23fc5adcf8e.json
+16
.sqlx/query-b157b94e003376d827b92eab1ff55caa773ed5691e2e555ab1d1f23fc5adcf8e.json
···
1
+
{
2
+
"db_name": "PostgreSQL",
3
+
"query": "INSERT INTO signal_kyber_pre_keys (id, identity, record, is_last_resort)\n VALUES ($1, $2, $3, TRUE)\n ON CONFLICT (id, identity) DO UPDATE SET is_last_resort = TRUE, record = $3",
4
+
"describe": {
5
+
"columns": [],
6
+
"parameters": {
7
+
"Left": [
8
+
"Int4",
9
+
"Text",
10
+
"Bytea"
11
+
]
12
+
},
13
+
"nullable": []
14
+
},
15
+
"hash": "b157b94e003376d827b92eab1ff55caa773ed5691e2e555ab1d1f23fc5adcf8e"
16
+
}
+22
.sqlx/query-b558892051ad793b4ae38a76d072e4ea440092663bd0d4ed9d48f5074788157a.json
+22
.sqlx/query-b558892051ad793b4ae38a76d072e4ea440092663bd0d4ed9d48f5074788157a.json
···
1
+
{
2
+
"db_name": "PostgreSQL",
3
+
"query": "SELECT MAX(id) FROM signal_pre_keys WHERE identity = $1",
4
+
"describe": {
5
+
"columns": [
6
+
{
7
+
"ordinal": 0,
8
+
"name": "max",
9
+
"type_info": "Int4"
10
+
}
11
+
],
12
+
"parameters": {
13
+
"Left": [
14
+
"Text"
15
+
]
16
+
},
17
+
"nullable": [
18
+
null
19
+
]
20
+
},
21
+
"hash": "b558892051ad793b4ae38a76d072e4ea440092663bd0d4ed9d48f5074788157a"
22
+
}
+25
.sqlx/query-b583ea011f17bd703a1dde860d1cc595a18c33dd0e37b575a71fa78f9fddc96f.json
+25
.sqlx/query-b583ea011f17bd703a1dde860d1cc595a18c33dd0e37b575a71fa78f9fddc96f.json
···
1
+
{
2
+
"db_name": "PostgreSQL",
3
+
"query": "SELECT record FROM signal_sender_keys\n WHERE address = $1 AND device_id = $2 AND identity = $3 AND distribution_id = $4",
4
+
"describe": {
5
+
"columns": [
6
+
{
7
+
"ordinal": 0,
8
+
"name": "record",
9
+
"type_info": "Bytea"
10
+
}
11
+
],
12
+
"parameters": {
13
+
"Left": [
14
+
"Text",
15
+
"Int4",
16
+
"Text",
17
+
"Uuid"
18
+
]
19
+
},
20
+
"nullable": [
21
+
false
22
+
]
23
+
},
24
+
"hash": "b583ea011f17bd703a1dde860d1cc595a18c33dd0e37b575a71fa78f9fddc96f"
25
+
}
+12
.sqlx/query-c08770c1ca1cb553e9067c26dec9a47d40f4cd3e16461cf0edbbb49020695f18.json
+12
.sqlx/query-c08770c1ca1cb553e9067c26dec9a47d40f4cd3e16461cf0edbbb49020695f18.json
+20
.sqlx/query-c130944c8791acb05ebf5f7b5b0f82b8c548ea9d516c0e9310fb46ffd3907977.json
+20
.sqlx/query-c130944c8791acb05ebf5f7b5b0f82b8c548ea9d516c0e9310fb46ffd3907977.json
···
1
+
{
2
+
"db_name": "PostgreSQL",
3
+
"query": "SELECT value FROM signal_kv WHERE key = 'registration'",
4
+
"describe": {
5
+
"columns": [
6
+
{
7
+
"ordinal": 0,
8
+
"name": "value",
9
+
"type_info": "Bytea"
10
+
}
11
+
],
12
+
"parameters": {
13
+
"Left": []
14
+
},
15
+
"nullable": [
16
+
false
17
+
]
18
+
},
19
+
"hash": "c130944c8791acb05ebf5f7b5b0f82b8c548ea9d516c0e9310fb46ffd3907977"
20
+
}
+16
.sqlx/query-c30d8f2bb8a20154b565a93108d3871289a752fb8d0de35a2164619da2c03aa0.json
+16
.sqlx/query-c30d8f2bb8a20154b565a93108d3871289a752fb8d0de35a2164619da2c03aa0.json
···
1
+
{
2
+
"db_name": "PostgreSQL",
3
+
"query": "WITH total AS (\n SELECT COUNT(*) AS cnt FROM signal_kyber_pre_keys\n WHERE identity = $1 AND is_last_resort = FALSE\n )\n DELETE FROM signal_kyber_pre_keys\n WHERE identity = $1 AND is_last_resort = FALSE\n AND stale_at IS NOT NULL AND stale_at < $2\n AND (SELECT cnt FROM total) > $3",
4
+
"describe": {
5
+
"columns": [],
6
+
"parameters": {
7
+
"Left": [
8
+
"Text",
9
+
"Timestamptz",
10
+
"Int8"
11
+
]
12
+
},
13
+
"nullable": []
14
+
},
15
+
"hash": "c30d8f2bb8a20154b565a93108d3871289a752fb8d0de35a2164619da2c03aa0"
16
+
}
+22
.sqlx/query-c5310fca925ec4188e761f218e98c11182e5757c40a70a2aa50af0f2896d98e7.json
+22
.sqlx/query-c5310fca925ec4188e761f218e98c11182e5757c40a70a2aa50af0f2896d98e7.json
···
1
+
{
2
+
"db_name": "PostgreSQL",
3
+
"query": "SELECT COUNT(*) AS \"count!\" FROM signal_signed_pre_keys WHERE identity = $1",
4
+
"describe": {
5
+
"columns": [
6
+
{
7
+
"ordinal": 0,
8
+
"name": "count!",
9
+
"type_info": "Int8"
10
+
}
11
+
],
12
+
"parameters": {
13
+
"Left": [
14
+
"Text"
15
+
]
16
+
},
17
+
"nullable": [
18
+
null
19
+
]
20
+
},
21
+
"hash": "c5310fca925ec4188e761f218e98c11182e5757c40a70a2aa50af0f2896d98e7"
22
+
}
+22
.sqlx/query-c67709e3fb975148fa86d9fd5ed5e1ef805b2f57a2ce5d955629d598e1ab2b80.json
+22
.sqlx/query-c67709e3fb975148fa86d9fd5ed5e1ef805b2f57a2ce5d955629d598e1ab2b80.json
···
1
+
{
2
+
"db_name": "PostgreSQL",
3
+
"query": "SELECT key FROM signal_profile_keys WHERE uuid = $1",
4
+
"describe": {
5
+
"columns": [
6
+
{
7
+
"ordinal": 0,
8
+
"name": "key",
9
+
"type_info": "Bytea"
10
+
}
11
+
],
12
+
"parameters": {
13
+
"Left": [
14
+
"Uuid"
15
+
]
16
+
},
17
+
"nullable": [
18
+
false
19
+
]
20
+
},
21
+
"hash": "c67709e3fb975148fa86d9fd5ed5e1ef805b2f57a2ce5d955629d598e1ab2b80"
22
+
}
+15
.sqlx/query-c749d53e4e38dd53aa2ac59ba2b15b641ace056515c34ec977bf47d74dfd7072.json
+15
.sqlx/query-c749d53e4e38dd53aa2ac59ba2b15b641ace056515c34ec977bf47d74dfd7072.json
···
1
+
{
2
+
"db_name": "PostgreSQL",
3
+
"query": "DELETE FROM signal_kyber_pre_keys\n WHERE id = $1 AND identity = $2 AND is_last_resort = FALSE",
4
+
"describe": {
5
+
"columns": [],
6
+
"parameters": {
7
+
"Left": [
8
+
"Int4",
9
+
"Text"
10
+
]
11
+
},
12
+
"nullable": []
13
+
},
14
+
"hash": "c749d53e4e38dd53aa2ac59ba2b15b641ace056515c34ec977bf47d74dfd7072"
15
+
}
+20
.sqlx/query-c86da12578b2e53e0bff374121b22244c4663820cbb6edfd8f0b8c9aa583cad2.json
+20
.sqlx/query-c86da12578b2e53e0bff374121b22244c4663820cbb6edfd8f0b8c9aa583cad2.json
···
1
+
{
2
+
"db_name": "PostgreSQL",
3
+
"query": "SELECT value FROM signal_kv WHERE key = 'master_key' LIMIT 1",
4
+
"describe": {
5
+
"columns": [
6
+
{
7
+
"ordinal": 0,
8
+
"name": "value",
9
+
"type_info": "Bytea"
10
+
}
11
+
],
12
+
"parameters": {
13
+
"Left": []
14
+
},
15
+
"nullable": [
16
+
false
17
+
]
18
+
},
19
+
"hash": "c86da12578b2e53e0bff374121b22244c4663820cbb6edfd8f0b8c9aa583cad2"
20
+
}
+20
.sqlx/query-dded08cb4fd0fc9bca55b3cf0c8d22f4e279bc8aedb72000f4c4bc093f61c750.json
+20
.sqlx/query-dded08cb4fd0fc9bca55b3cf0c8d22f4e279bc8aedb72000f4c4bc093f61c750.json
···
1
+
{
2
+
"db_name": "PostgreSQL",
3
+
"query": "SELECT value FROM signal_kv WHERE key = 'sender_certificate' LIMIT 1",
4
+
"describe": {
5
+
"columns": [
6
+
{
7
+
"ordinal": 0,
8
+
"name": "value",
9
+
"type_info": "Bytea"
10
+
}
11
+
],
12
+
"parameters": {
13
+
"Left": []
14
+
},
15
+
"nullable": [
16
+
false
17
+
]
18
+
},
19
+
"hash": "dded08cb4fd0fc9bca55b3cf0c8d22f4e279bc8aedb72000f4c4bc093f61c750"
20
+
}
+16
.sqlx/query-def40c1cfac196a066d81fb0efa0fa7bdf5f242bd13c8b70e47a512c5e9df5b1.json
+16
.sqlx/query-def40c1cfac196a066d81fb0efa0fa7bdf5f242bd13c8b70e47a512c5e9df5b1.json
···
1
+
{
2
+
"db_name": "PostgreSQL",
3
+
"query": "INSERT INTO signal_signed_pre_keys (id, identity, record)\n VALUES ($1, $2, $3)\n ON CONFLICT (id, identity) DO UPDATE SET record = $3",
4
+
"describe": {
5
+
"columns": [],
6
+
"parameters": {
7
+
"Left": [
8
+
"Int4",
9
+
"Text",
10
+
"Bytea"
11
+
]
12
+
},
13
+
"nullable": []
14
+
},
15
+
"hash": "def40c1cfac196a066d81fb0efa0fa7bdf5f242bd13c8b70e47a512c5e9df5b1"
16
+
}
+12
.sqlx/query-e2ed0b4bfe13a99be85311fcc6e3c2dbdb789b9a44c0122f736ead48f4713a5b.json
+12
.sqlx/query-e2ed0b4bfe13a99be85311fcc6e3c2dbdb789b9a44c0122f736ead48f4713a5b.json
+15
.sqlx/query-eb837730e87ff990c4441d7bdab001d7542d1803702c634a6099365a9740e45a.json
+15
.sqlx/query-eb837730e87ff990c4441d7bdab001d7542d1803702c634a6099365a9740e45a.json
···
1
+
{
2
+
"db_name": "PostgreSQL",
3
+
"query": "DELETE FROM signal_kyber_pre_keys WHERE id = $1 AND identity = $2",
4
+
"describe": {
5
+
"columns": [],
6
+
"parameters": {
7
+
"Left": [
8
+
"Int4",
9
+
"Text"
10
+
]
11
+
},
12
+
"nullable": []
13
+
},
14
+
"hash": "eb837730e87ff990c4441d7bdab001d7542d1803702c634a6099365a9740e45a"
15
+
}
+22
.sqlx/query-eea566212ffce269028a8623a12b553c048ef1ea433aa5567e72b2b639f69b0d.json
+22
.sqlx/query-eea566212ffce269028a8623a12b553c048ef1ea433aa5567e72b2b639f69b0d.json
···
1
+
{
2
+
"db_name": "PostgreSQL",
3
+
"query": "SELECT MAX(id) FROM signal_kyber_pre_keys WHERE identity = $1",
4
+
"describe": {
5
+
"columns": [
6
+
{
7
+
"ordinal": 0,
8
+
"name": "max",
9
+
"type_info": "Int4"
10
+
}
11
+
],
12
+
"parameters": {
13
+
"Left": [
14
+
"Text"
15
+
]
16
+
},
17
+
"nullable": [
18
+
null
19
+
]
20
+
},
21
+
"hash": "eea566212ffce269028a8623a12b553c048ef1ea433aa5567e72b2b639f69b0d"
22
+
}
+16
.sqlx/query-efcf513bba65213ed4b71259a7016ffd7b1b8ff85206416a86beba19323a3be7.json
+16
.sqlx/query-efcf513bba65213ed4b71259a7016ffd7b1b8ff85206416a86beba19323a3be7.json
···
1
+
{
2
+
"db_name": "PostgreSQL",
3
+
"query": "DELETE FROM signal_sessions WHERE address = $1 AND device_id = $2 AND identity = $3",
4
+
"describe": {
5
+
"columns": [],
6
+
"parameters": {
7
+
"Left": [
8
+
"Text",
9
+
"Int4",
10
+
"Text"
11
+
]
12
+
},
13
+
"nullable": []
14
+
},
15
+
"hash": "efcf513bba65213ed4b71259a7016ffd7b1b8ff85206416a86beba19323a3be7"
16
+
}
+24
.sqlx/query-f332e618e59a298573c4b6b6c7a12252b461a6676f2d797c5dae5a0baee016a7.json
+24
.sqlx/query-f332e618e59a298573c4b6b6c7a12252b461a6676f2d797c5dae5a0baee016a7.json
···
1
+
{
2
+
"db_name": "PostgreSQL",
3
+
"query": "SELECT record FROM signal_sessions\n WHERE address = $1 AND device_id = $2 AND identity = $3",
4
+
"describe": {
5
+
"columns": [
6
+
{
7
+
"ordinal": 0,
8
+
"name": "record",
9
+
"type_info": "Bytea"
10
+
}
11
+
],
12
+
"parameters": {
13
+
"Left": [
14
+
"Text",
15
+
"Int4",
16
+
"Text"
17
+
]
18
+
},
19
+
"nullable": [
20
+
false
21
+
]
22
+
},
23
+
"hash": "f332e618e59a298573c4b6b6c7a12252b461a6676f2d797c5dae5a0baee016a7"
24
+
}
+22
.sqlx/query-f41749b35c081fc9d0881c7e2fc988e7c4d164ab5996f18e9f3a29fe4d183db9.json
+22
.sqlx/query-f41749b35c081fc9d0881c7e2fc988e7c4d164ab5996f18e9f3a29fe4d183db9.json
···
1
+
{
2
+
"db_name": "PostgreSQL",
3
+
"query": "SELECT MAX(id) FROM signal_signed_pre_keys WHERE identity = $1",
4
+
"describe": {
5
+
"columns": [
6
+
{
7
+
"ordinal": 0,
8
+
"name": "max",
9
+
"type_info": "Int4"
10
+
}
11
+
],
12
+
"parameters": {
13
+
"Left": [
14
+
"Text"
15
+
]
16
+
},
17
+
"nullable": [
18
+
null
19
+
]
20
+
},
21
+
"hash": "f41749b35c081fc9d0881c7e2fc988e7c4d164ab5996f18e9f3a29fe4d183db9"
22
+
}
+1226
-103
Cargo.lock
+1226
-103
Cargo.lock
···
46
46
"cfg-if",
47
47
"cipher",
48
48
"cpufeatures",
49
+
"zeroize",
49
50
]
50
51
51
52
[[package]]
···
62
63
"subtle",
63
64
]
64
65
66
+
[[package]]
67
+
name = "aes-gcm-siv"
68
+
version = "0.11.1"
69
+
source = "registry+https://github.com/rust-lang/crates.io-index"
70
+
checksum = "ae0784134ba9375416d469ec31e7c5f9fa94405049cf08c5ce5b4698be673e0d"
71
+
dependencies = [
72
+
"aead",
73
+
"aes",
74
+
"cipher",
75
+
"ctr",
76
+
"polyval",
77
+
"subtle",
78
+
"zeroize",
79
+
]
80
+
65
81
[[package]]
66
82
name = "ahash"
67
83
version = "0.8.12"
···
181
197
source = "registry+https://github.com/rust-lang/crates.io-index"
182
198
checksum = "03918c3dbd7701a85c6b9887732e2921175f26c350b4563841d0958c21d57e6d"
183
199
200
+
[[package]]
201
+
name = "argon2"
202
+
version = "0.5.3"
203
+
source = "registry+https://github.com/rust-lang/crates.io-index"
204
+
checksum = "3c3610892ee6e0cbce8ae2700349fcf8f98adb0dbfbee85aec3c9179d29cc072"
205
+
dependencies = [
206
+
"base64ct",
207
+
"blake2",
208
+
"cpufeatures",
209
+
"password-hash",
210
+
"zeroize",
211
+
]
212
+
184
213
[[package]]
185
214
name = "asn1-rs"
186
215
version = "0.6.2"
···
230
259
"serde_json",
231
260
]
232
261
262
+
[[package]]
263
+
name = "assert_matches"
264
+
version = "1.5.0"
265
+
source = "registry+https://github.com/rust-lang/crates.io-index"
266
+
checksum = "9b34d609dfbaf33d6889b2b7106d3ca345eacad44200913df5ba02bfd31d2ba9"
267
+
233
268
[[package]]
234
269
name = "astral-tokio-tar"
235
270
version = "0.5.6"
···
292
327
"syn 2.0.111",
293
328
]
294
329
330
+
[[package]]
331
+
name = "async-tungstenite"
332
+
version = "0.28.2"
333
+
source = "registry+https://github.com/rust-lang/crates.io-index"
334
+
checksum = "1c348fb0b6d132c596eca3dcd941df48fb597aafcb07a738ec41c004b087dc99"
335
+
dependencies = [
336
+
"atomic-waker",
337
+
"futures-core",
338
+
"futures-io",
339
+
"futures-task",
340
+
"futures-util",
341
+
"log",
342
+
"pin-project-lite",
343
+
"tungstenite 0.24.0",
344
+
]
345
+
295
346
[[package]]
296
347
name = "atoi"
297
348
version = "2.0.0"
···
854
905
source = "registry+https://github.com/rust-lang/crates.io-index"
855
906
checksum = "b5e9430d9a245a77c92176e649af6e275f20839a48389859d1661e9a128d077c"
856
907
dependencies = [
857
-
"const-str",
908
+
"const-str 0.4.3",
858
909
"match-lookup",
859
910
]
860
911
···
916
967
"zeroize",
917
968
]
918
969
970
+
[[package]]
971
+
name = "bincode"
972
+
version = "1.3.3"
973
+
source = "registry+https://github.com/rust-lang/crates.io-index"
974
+
checksum = "b1f45e9417d87227c7a56d22e471c6206462cba514c7590c09aff4cf6d1ddcad"
975
+
dependencies = [
976
+
"serde",
977
+
]
978
+
919
979
[[package]]
920
980
name = "bincode"
921
981
version = "2.0.1"
···
945
1005
"serde_core",
946
1006
]
947
1007
1008
+
[[package]]
1009
+
name = "blake2"
1010
+
version = "0.10.6"
1011
+
source = "registry+https://github.com/rust-lang/crates.io-index"
1012
+
checksum = "46502ad458c9a52b69d4d4d32775c788b7a1b85e8bc9d482d92250fc0e3f8efe"
1013
+
dependencies = [
1014
+
"digest",
1015
+
]
1016
+
948
1017
[[package]]
949
1018
name = "block-buffer"
950
1019
version = "0.10.4"
···
954
1023
"generic-array",
955
1024
]
956
1025
1026
+
[[package]]
1027
+
name = "block-padding"
1028
+
version = "0.3.3"
1029
+
source = "registry+https://github.com/rust-lang/crates.io-index"
1030
+
checksum = "a8894febbff9f758034a5b8e12d87918f56dfc64a8e1fe757d65e29041538d93"
1031
+
dependencies = [
1032
+
"generic-array",
1033
+
]
1034
+
957
1035
[[package]]
958
1036
name = "blowfish"
959
1037
version = "0.9.1"
···
1017
1095
source = "registry+https://github.com/rust-lang/crates.io-index"
1018
1096
checksum = "85a885520bf6249ab931a764ffdb87b0ceef48e6e7d807cfdb21b751e086e1ad"
1019
1097
dependencies = [
1020
-
"prost",
1021
-
"prost-types",
1098
+
"prost 0.14.1",
1099
+
"prost-types 0.14.1",
1022
1100
"tonic",
1023
1101
"tonic-prost",
1024
1102
"ureq",
···
1034
1112
"bollard-buildkit-proto",
1035
1113
"bytes",
1036
1114
"chrono",
1037
-
"prost",
1115
+
"prost 0.14.1",
1038
1116
"serde",
1039
1117
"serde_json",
1040
1118
"serde_repr",
···
1137
1215
version = "1.11.0"
1138
1216
source = "registry+https://github.com/rust-lang/crates.io-index"
1139
1217
checksum = "b35204fbdc0b3f4446b89fc1ac2cf84a8a68971995d0bf2e925ec7cd960f9cb3"
1218
+
dependencies = [
1219
+
"serde",
1220
+
]
1140
1221
1141
1222
[[package]]
1142
1223
name = "bytes-utils"
···
1148
1229
"either",
1149
1230
]
1150
1231
1232
+
[[package]]
1233
+
name = "cbc"
1234
+
version = "0.1.2"
1235
+
source = "registry+https://github.com/rust-lang/crates.io-index"
1236
+
checksum = "26b52a9543ae338f279b96b0b9fed9c8093744685043739079ce85cd58f289a6"
1237
+
dependencies = [
1238
+
"cipher",
1239
+
]
1240
+
1151
1241
[[package]]
1152
1242
name = "cbor4ii"
1153
1243
version = "0.2.14"
···
1264
1354
dependencies = [
1265
1355
"crypto-common",
1266
1356
"inout",
1357
+
"zeroize",
1267
1358
]
1268
1359
1269
1360
[[package]]
···
1411
1502
source = "registry+https://github.com/rust-lang/crates.io-index"
1412
1503
checksum = "2f421161cb492475f1661ddc9815a745a1c894592070661180fdec3d4872e9c3"
1413
1504
1505
+
[[package]]
1506
+
name = "const-str"
1507
+
version = "1.1.0"
1508
+
source = "registry+https://github.com/rust-lang/crates.io-index"
1509
+
checksum = "18f12cc9948ed9604230cdddc7c86e270f9401ccbe3c2e98a4378c5e7632212f"
1510
+
1414
1511
[[package]]
1415
1512
name = "constant_time_eq"
1416
1513
version = "0.3.1"
···
1453
1550
source = "registry+https://github.com/rust-lang/crates.io-index"
1454
1551
checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b"
1455
1552
1553
+
[[package]]
1554
+
name = "core-models"
1555
+
version = "0.0.4"
1556
+
source = "registry+https://github.com/rust-lang/crates.io-index"
1557
+
checksum = "0940496e5c83c54f3b753d5317daec82e8edac71c33aaa1f666d76f518de2444"
1558
+
dependencies = [
1559
+
"hax-lib",
1560
+
"pastey",
1561
+
"rand 0.9.2",
1562
+
]
1563
+
1456
1564
[[package]]
1457
1565
name = "core2"
1458
1566
version = "0.4.0"
···
1514
1622
source = "registry+https://github.com/rust-lang/crates.io-index"
1515
1623
checksum = "790eea4361631c5e7d22598ecd5723ff611904e3344ce8720784c93e3d83d40b"
1516
1624
1625
+
[[package]]
1626
+
name = "crossbeam-deque"
1627
+
version = "0.8.6"
1628
+
source = "registry+https://github.com/rust-lang/crates.io-index"
1629
+
checksum = "9dd111b7b7f7d55b72c0a6ae361660ee5853c9af73f70c3c2ef6858b950e2e51"
1630
+
dependencies = [
1631
+
"crossbeam-epoch",
1632
+
"crossbeam-utils",
1633
+
]
1634
+
1517
1635
[[package]]
1518
1636
name = "crossbeam-epoch"
1519
1637
version = "0.9.18"
···
1607
1725
[[package]]
1608
1726
name = "curve25519-dalek"
1609
1727
version = "4.1.3"
1610
-
source = "registry+https://github.com/rust-lang/crates.io-index"
1611
-
checksum = "97fb8b7c4503de7d6ae7b42ab72a5a59857b4c937ec27a3d4539dba95b5ab2be"
1728
+
source = "git+https://github.com/signalapp/curve25519-dalek?tag=signal-curve25519-4.1.3#7c6d34756355a3566a704da84dce7b1c039a6572"
1612
1729
dependencies = [
1613
1730
"cfg-if",
1614
1731
"cpufeatures",
1615
1732
"curve25519-dalek-derive",
1616
1733
"digest",
1617
1734
"fiat-crypto",
1735
+
"rand_core 0.6.4",
1618
1736
"rustc_version",
1737
+
"serde",
1619
1738
"subtle",
1620
1739
"zeroize",
1621
1740
]
···
1623
1742
[[package]]
1624
1743
name = "curve25519-dalek-derive"
1625
1744
version = "0.1.1"
1626
-
source = "registry+https://github.com/rust-lang/crates.io-index"
1627
-
checksum = "f46882e17999c6cc590af592290432be3bce0428cb0d5f8b6715e4dc7b383eb3"
1745
+
source = "git+https://github.com/signalapp/curve25519-dalek?tag=signal-curve25519-4.1.3#7c6d34756355a3566a704da84dce7b1c039a6572"
1628
1746
dependencies = [
1629
1747
"proc-macro2",
1630
1748
"quote",
···
1769
1887
"serde_core",
1770
1888
]
1771
1889
1890
+
[[package]]
1891
+
name = "derive-where"
1892
+
version = "1.6.1"
1893
+
source = "registry+https://github.com/rust-lang/crates.io-index"
1894
+
checksum = "d08b3a0bcc0d079199cd476b2cae8435016ec11d1c0986c6901c5ac223041534"
1895
+
dependencies = [
1896
+
"proc-macro2",
1897
+
"quote",
1898
+
"syn 2.0.111",
1899
+
]
1900
+
1772
1901
[[package]]
1773
1902
name = "derive_arbitrary"
1774
1903
version = "1.4.2"
···
1786
1915
source = "registry+https://github.com/rust-lang/crates.io-index"
1787
1916
checksum = "4a9b99b9cbbe49445b21764dc0625032a89b145a2642e67603e1c936f5458d05"
1788
1917
dependencies = [
1789
-
"derive_more-impl",
1918
+
"derive_more-impl 1.0.0",
1919
+
]
1920
+
1921
+
[[package]]
1922
+
name = "derive_more"
1923
+
version = "2.1.1"
1924
+
source = "registry+https://github.com/rust-lang/crates.io-index"
1925
+
checksum = "d751e9e49156b02b44f9c1815bcb94b984cdcc4396ecc32521c739452808b134"
1926
+
dependencies = [
1927
+
"derive_more-impl 2.1.1",
1790
1928
]
1791
1929
1792
1930
[[package]]
···
1801
1939
"unicode-xid",
1802
1940
]
1803
1941
1942
+
[[package]]
1943
+
name = "derive_more-impl"
1944
+
version = "2.1.1"
1945
+
source = "registry+https://github.com/rust-lang/crates.io-index"
1946
+
checksum = "799a97264921d8623a957f6c3b9011f3b5492f557bbb7a5a19b7fa6d06ba8dcb"
1947
+
dependencies = [
1948
+
"proc-macro2",
1949
+
"quote",
1950
+
"rustc_version",
1951
+
"syn 2.0.111",
1952
+
"unicode-xid",
1953
+
]
1954
+
1804
1955
[[package]]
1805
1956
name = "diatomic-waker"
1806
1957
version = "0.2.3"
···
2126
2277
source = "registry+https://github.com/rust-lang/crates.io-index"
2127
2278
checksum = "3a3076410a55c90011c298b04d0cfa770b00fa04e1e3c97d3f6c9de105a03844"
2128
2279
2280
+
[[package]]
2281
+
name = "fixedbitset"
2282
+
version = "0.5.7"
2283
+
source = "registry+https://github.com/rust-lang/crates.io-index"
2284
+
checksum = "1d674e81391d1e1ab681a28d99df07927c6d4aa5b027d7da16ba32d1d21ecd99"
2285
+
2129
2286
[[package]]
2130
2287
name = "flate2"
2131
2288
version = "1.1.5"
···
2160
2317
source = "registry+https://github.com/rust-lang/crates.io-index"
2161
2318
checksum = "1f59e967f3f675997e4a4a6b99d2a75148d59d64c46211b78b4f34ebb951b273"
2162
2319
dependencies = [
2163
-
"bincode",
2320
+
"bincode 2.0.1",
2164
2321
"bytes",
2165
2322
"rand 0.9.2",
2166
2323
"serde",
···
2402
2559
dependencies = [
2403
2560
"opaque-debug",
2404
2561
"polyval",
2562
+
"zeroize",
2405
2563
]
2406
2564
2407
2565
[[package]]
···
2572
2730
"hashbrown 0.15.5",
2573
2731
]
2574
2732
2733
+
[[package]]
2734
+
name = "hax-lib"
2735
+
version = "0.3.5"
2736
+
source = "registry+https://github.com/rust-lang/crates.io-index"
2737
+
checksum = "74d9ba66d1739c68e0219b2b2238b5c4145f491ebf181b9c6ab561a19352ae86"
2738
+
dependencies = [
2739
+
"hax-lib-macros",
2740
+
"num-bigint",
2741
+
"num-traits",
2742
+
]
2743
+
2744
+
[[package]]
2745
+
name = "hax-lib-macros"
2746
+
version = "0.3.5"
2747
+
source = "registry+https://github.com/rust-lang/crates.io-index"
2748
+
checksum = "24ba777a231a58d1bce1d68313fa6b6afcc7966adef23d60f45b8a2b9b688bf1"
2749
+
dependencies = [
2750
+
"hax-lib-macros-types",
2751
+
"proc-macro-error2",
2752
+
"proc-macro2",
2753
+
"quote",
2754
+
"syn 2.0.111",
2755
+
]
2756
+
2757
+
[[package]]
2758
+
name = "hax-lib-macros-types"
2759
+
version = "0.3.5"
2760
+
source = "registry+https://github.com/rust-lang/crates.io-index"
2761
+
checksum = "867e19177d7425140b417cd27c2e05320e727ee682e98368f88b7194e80ad515"
2762
+
dependencies = [
2763
+
"proc-macro2",
2764
+
"quote",
2765
+
"serde",
2766
+
"serde_json",
2767
+
"uuid",
2768
+
]
2769
+
2575
2770
[[package]]
2576
2771
name = "heapless"
2577
2772
version = "0.7.17"
···
2688
2883
"windows-sys 0.61.2",
2689
2884
]
2690
2885
2886
+
[[package]]
2887
+
name = "hpke-rs"
2888
+
version = "0.5.0"
2889
+
source = "registry+https://github.com/rust-lang/crates.io-index"
2890
+
checksum = "c8c09b01d75373842d3123a4dd51bad5cb70e95d8b96e50bc20d08877a8d2443"
2891
+
dependencies = [
2892
+
"hpke-rs-crypto",
2893
+
"libcrux-sha3 0.0.4",
2894
+
"log",
2895
+
"rand_core 0.9.3",
2896
+
"zeroize",
2897
+
]
2898
+
2899
+
[[package]]
2900
+
name = "hpke-rs-crypto"
2901
+
version = "0.4.0"
2902
+
source = "registry+https://github.com/rust-lang/crates.io-index"
2903
+
checksum = "2dd92b7d7f0deaae59c152e01c01f5280ea92dfac82090e5c025879b32df9193"
2904
+
dependencies = [
2905
+
"rand_core 0.9.3",
2906
+
]
2907
+
2691
2908
[[package]]
2692
2909
name = "http"
2693
2910
version = "0.2.12"
···
3117
3334
source = "registry+https://github.com/rust-lang/crates.io-index"
3118
3335
checksum = "879f10e63c20629ecabbb64a8010319738c66a5cd0c29b02d63d272b03751d01"
3119
3336
dependencies = [
3337
+
"block-padding",
3120
3338
"generic-array",
3121
3339
]
3122
3340
···
3398
3616
checksum = "37c93d8daa9d8a012fd8ab92f088405fb202ea0b6ab73ee2482ae66af4f42091"
3399
3617
3400
3618
[[package]]
3401
-
name = "libm"
3402
-
version = "0.2.15"
3619
+
name = "libcrux-hacl-rs"
3620
+
version = "0.0.4"
3403
3621
source = "registry+https://github.com/rust-lang/crates.io-index"
3404
-
checksum = "f9fbbcab51052fe104eb5e5d351cf728d30a5be1fe14d9be8a3b097481fb97de"
3622
+
checksum = "2637dc87d158e1f1b550fd9b226443e84153fded4de69028d897b534d16d22e6"
3623
+
dependencies = [
3624
+
"libcrux-macros",
3625
+
]
3405
3626
3406
3627
[[package]]
3407
-
name = "libredox"
3408
-
version = "0.1.11"
3628
+
name = "libcrux-hmac"
3629
+
version = "0.0.4"
3409
3630
source = "registry+https://github.com/rust-lang/crates.io-index"
3410
-
checksum = "df15f6eac291ed1cf25865b1ee60399f57e7c227e7f51bdbd4c5270396a9ed50"
3631
+
checksum = "9f0e8011bfcdb6059127e673ec0e1fc7b2a3705c683ade9d708875ed4c26cd8d"
3411
3632
dependencies = [
3412
-
"bitflags",
3413
-
"libc",
3414
-
"redox_syscall 0.6.0",
3633
+
"libcrux-hacl-rs",
3634
+
"libcrux-macros",
3635
+
"libcrux-sha2",
3415
3636
]
3416
3637
3417
3638
[[package]]
3418
-
name = "libsqlite3-sys"
3419
-
version = "0.30.1"
3639
+
name = "libcrux-intrinsics"
3640
+
version = "0.0.4"
3420
3641
source = "registry+https://github.com/rust-lang/crates.io-index"
3421
-
checksum = "2e99fb7a497b1e3339bc746195567ed8d3e24945ecd636e3619d20b9de9e9149"
3642
+
checksum = "bc9ee7ef66569dd7516454fe26de4e401c0c62073929803486b96744594b9632"
3422
3643
dependencies = [
3423
-
"pkg-config",
3424
-
"vcpkg",
3644
+
"core-models",
3645
+
"hax-lib",
3425
3646
]
3426
3647
3427
3648
[[package]]
3428
-
name = "libz-rs-sys"
3429
-
version = "0.5.5"
3649
+
name = "libcrux-macros"
3650
+
version = "0.0.3"
3430
3651
source = "registry+https://github.com/rust-lang/crates.io-index"
3431
-
checksum = "c10501e7805cee23da17c7790e59df2870c0d4043ec6d03f67d31e2b53e77415"
3652
+
checksum = "ffd6aa2dcd5be681662001b81d493f1569c6d49a32361f470b0c955465cd0338"
3432
3653
dependencies = [
3433
-
"zlib-rs",
3654
+
"quote",
3655
+
"syn 2.0.111",
3434
3656
]
3435
3657
3436
3658
[[package]]
3437
-
name = "linked-hash-map"
3438
-
version = "0.5.6"
3659
+
name = "libcrux-ml-kem"
3660
+
version = "0.0.5"
3439
3661
source = "registry+https://github.com/rust-lang/crates.io-index"
3440
-
checksum = "0717cef1bc8b636c6e1c1bbdefc09e6322da8a9321966e8928ef80d20f7f770f"
3662
+
checksum = "22a36f21056e552438dbe6ce413b6682001795e53bd1f0e2c941d7e231238e5a"
3663
+
dependencies = [
3664
+
"hax-lib",
3665
+
"libcrux-intrinsics",
3666
+
"libcrux-platform 0.0.3",
3667
+
"libcrux-secrets",
3668
+
"libcrux-sha3 0.0.5",
3669
+
"libcrux-traits",
3670
+
]
3441
3671
3442
3672
[[package]]
3443
-
name = "linux-raw-sys"
3444
-
version = "0.11.0"
3673
+
name = "libcrux-platform"
3674
+
version = "0.0.2"
3445
3675
source = "registry+https://github.com/rust-lang/crates.io-index"
3446
-
checksum = "df1d3c3b53da64cf5760482273a98e575c651a67eec7f77df96b5b642de8f039"
3676
+
checksum = "db82d058aa76ea315a3b2092f69dfbd67ddb0e462038a206e1dcd73f058c0778"
3677
+
dependencies = [
3678
+
"libc",
3679
+
]
3447
3680
3448
3681
[[package]]
3449
-
name = "litemap"
3450
-
version = "0.8.1"
3682
+
name = "libcrux-platform"
3683
+
version = "0.0.3"
3451
3684
source = "registry+https://github.com/rust-lang/crates.io-index"
3452
-
checksum = "6373607a59f0be73a39b6fe456b8192fcc3585f602af20751600e974dd455e77"
3685
+
checksum = "1d9e21d7ed31a92ac539bd69a8c970b183ee883872d2d19ce27036e24cb8ecc4"
3686
+
dependencies = [
3687
+
"libc",
3688
+
]
3453
3689
3454
3690
[[package]]
3455
-
name = "lock_api"
3456
-
version = "0.4.14"
3691
+
name = "libcrux-secrets"
3692
+
version = "0.0.4"
3457
3693
source = "registry+https://github.com/rust-lang/crates.io-index"
3458
-
checksum = "224399e74b87b5f3557511d98dff8b14089b3dadafcab6bb93eab67d3aace965"
3694
+
checksum = "6e4dbbf6bc9f2bc0f20dc3bea3e5c99adff3bdccf6d2a40488963da69e2ec307"
3459
3695
dependencies = [
3460
-
"scopeguard",
3696
+
"hax-lib",
3461
3697
]
3462
3698
3463
3699
[[package]]
3464
-
name = "log"
3465
-
version = "0.4.29"
3700
+
name = "libcrux-sha2"
3701
+
version = "0.0.4"
3466
3702
source = "registry+https://github.com/rust-lang/crates.io-index"
3467
-
checksum = "5e5032e24019045c762d3c0f28f5b6b8bbf38563a65908389bf7978758920897"
3703
+
checksum = "649d9401e6e1954f58531b8eb13b12c800f85bbadc93362871b63a1f8a8d6d32"
3704
+
dependencies = [
3705
+
"libcrux-hacl-rs",
3706
+
"libcrux-macros",
3707
+
"libcrux-traits",
3708
+
]
3468
3709
3469
3710
[[package]]
3470
-
name = "loom"
3471
-
version = "0.7.2"
3711
+
name = "libcrux-sha3"
3712
+
version = "0.0.4"
3472
3713
source = "registry+https://github.com/rust-lang/crates.io-index"
3473
-
checksum = "419e0dc8046cb947daa77eb95ae174acfbddb7673b4151f56d1eed8e93fbfaca"
3714
+
checksum = "2400bec764d1c75b8a496d5747cffe32f1fb864a12577f0aca2f55a92021c962"
3474
3715
dependencies = [
3475
-
"cfg-if",
3476
-
"generator",
3477
-
"scoped-tls",
3478
-
"tracing",
3479
-
"tracing-subscriber",
3716
+
"hax-lib",
3717
+
"libcrux-intrinsics",
3718
+
"libcrux-platform 0.0.2",
3719
+
"libcrux-traits",
3480
3720
]
3481
3721
3482
3722
[[package]]
3483
-
name = "lru"
3484
-
version = "0.12.5"
3723
+
name = "libcrux-sha3"
3724
+
version = "0.0.5"
3485
3725
source = "registry+https://github.com/rust-lang/crates.io-index"
3486
-
checksum = "234cf4f4a04dc1f57e24b96cc0cd600cf2af460d4161ac5ecdd0af8e1f3b2a38"
3726
+
checksum = "18e869fdeb9af62c55c3fcd60ce407552eb282d727550ce986abac94a3474479"
3487
3727
dependencies = [
3488
-
"hashbrown 0.15.5",
3728
+
"hax-lib",
3729
+
"libcrux-intrinsics",
3730
+
"libcrux-platform 0.0.3",
3731
+
"libcrux-traits",
3489
3732
]
3490
3733
3491
3734
[[package]]
3492
-
name = "lru-cache"
3493
-
version = "0.1.2"
3735
+
name = "libcrux-traits"
3736
+
version = "0.0.4"
3494
3737
source = "registry+https://github.com/rust-lang/crates.io-index"
3495
-
checksum = "31e24f1ad8321ca0e8a1e0ac13f23cb668e6f5466c2c57319f6a5cf1cc8e3b1c"
3738
+
checksum = "9adfd58e79d860f6b9e40e35127bfae9e5bd3ade33201d1347459011a2add034"
3496
3739
dependencies = [
3497
-
"linked-hash-map",
3740
+
"libcrux-secrets",
3741
+
"rand 0.9.2",
3498
3742
]
3499
3743
3500
3744
[[package]]
3501
-
name = "lru-slab"
3502
-
version = "0.1.2"
3745
+
name = "libm"
3746
+
version = "0.2.15"
3503
3747
source = "registry+https://github.com/rust-lang/crates.io-index"
3504
-
checksum = "112b39cec0b298b6c1999fee3e31427f74f676e4cb9879ed1a121b43661a4154"
3748
+
checksum = "f9fbbcab51052fe104eb5e5d351cf728d30a5be1fe14d9be8a3b097481fb97de"
3505
3749
3506
3750
[[package]]
3507
-
name = "match-lookup"
3508
-
version = "0.1.1"
3751
+
name = "libredox"
3752
+
version = "0.1.11"
3509
3753
source = "registry+https://github.com/rust-lang/crates.io-index"
3510
-
checksum = "1265724d8cb29dbbc2b0f06fffb8bf1a8c0cf73a78eede9ba73a4a66c52a981e"
3754
+
checksum = "df15f6eac291ed1cf25865b1ee60399f57e7c227e7f51bdbd4c5270396a9ed50"
3511
3755
dependencies = [
3512
-
"proc-macro2",
3513
-
"quote",
3514
-
"syn 1.0.109",
3756
+
"bitflags",
3757
+
"libc",
3758
+
"redox_syscall 0.6.0",
3759
+
]
3760
+
3761
+
[[package]]
3762
+
name = "libsignal-account-keys"
3763
+
version = "0.1.0"
3764
+
source = "git+https://github.com/signalapp/libsignal?tag=v0.87.4#38514bdc8acaaffbccd5c96515c68deb2019abe0"
3765
+
dependencies = [
3766
+
"argon2",
3767
+
"derive_more 2.1.1",
3768
+
"displaydoc",
3769
+
"hkdf",
3770
+
"libsignal-core",
3771
+
"partial-default",
3772
+
"protobuf",
3773
+
"protobuf-codegen",
3774
+
"rand 0.9.2",
3775
+
"rand_core 0.9.3",
3776
+
"serde",
3777
+
"sha2",
3778
+
"signal-crypto",
3779
+
"static_assertions",
3780
+
"thiserror 2.0.17",
3781
+
"zerocopy",
3782
+
]
3783
+
3784
+
[[package]]
3785
+
name = "libsignal-core"
3786
+
version = "0.1.0"
3787
+
source = "git+https://github.com/signalapp/libsignal?tag=v0.87.4#38514bdc8acaaffbccd5c96515c68deb2019abe0"
3788
+
dependencies = [
3789
+
"curve25519-dalek",
3790
+
"derive_more 2.1.1",
3791
+
"displaydoc",
3792
+
"log",
3793
+
"rand 0.9.2",
3794
+
"sha2",
3795
+
"subtle",
3796
+
"thiserror 2.0.17",
3797
+
"uuid",
3798
+
"x25519-dalek",
3799
+
"zerocopy",
3800
+
]
3801
+
3802
+
[[package]]
3803
+
name = "libsignal-protocol"
3804
+
version = "0.1.0"
3805
+
source = "git+https://github.com/signalapp/libsignal?tag=v0.87.4#38514bdc8acaaffbccd5c96515c68deb2019abe0"
3806
+
dependencies = [
3807
+
"aes",
3808
+
"aes-gcm-siv",
3809
+
"assert_matches",
3810
+
"async-trait",
3811
+
"bitflags",
3812
+
"const-str 1.1.0",
3813
+
"ctr",
3814
+
"data-encoding-macro",
3815
+
"derive-where",
3816
+
"derive_more 2.1.1",
3817
+
"displaydoc",
3818
+
"hex",
3819
+
"hkdf",
3820
+
"hmac",
3821
+
"indexmap 2.12.1",
3822
+
"itertools",
3823
+
"libcrux-ml-kem",
3824
+
"libsignal-core",
3825
+
"log",
3826
+
"prost 0.14.1",
3827
+
"prost-build 0.14.1",
3828
+
"rand 0.9.2",
3829
+
"rayon",
3830
+
"serde",
3831
+
"sha2",
3832
+
"signal-crypto",
3833
+
"spqr",
3834
+
"subtle",
3835
+
"thiserror 2.0.17",
3836
+
"uuid",
3837
+
"zerocopy",
3838
+
]
3839
+
3840
+
[[package]]
3841
+
name = "libsignal-service"
3842
+
version = "0.1.0"
3843
+
source = "git+https://github.com/whisperfish/libsignal-service-rs?rev=3d07d8df33482b2d191c075fdc2b750738a89384#3d07d8df33482b2d191c075fdc2b750738a89384"
3844
+
dependencies = [
3845
+
"aes",
3846
+
"aes-gcm",
3847
+
"async-trait",
3848
+
"base64 0.22.1",
3849
+
"bincode 1.3.3",
3850
+
"bytes",
3851
+
"cbc",
3852
+
"chrono",
3853
+
"ctr",
3854
+
"derive_more 2.1.1",
3855
+
"futures",
3856
+
"hex",
3857
+
"hkdf",
3858
+
"hmac",
3859
+
"libsignal-core",
3860
+
"libsignal-protocol",
3861
+
"phonenumber",
3862
+
"prost 0.13.5",
3863
+
"prost-build 0.13.5",
3864
+
"rand 0.9.2",
3865
+
"rand_core 0.6.4",
3866
+
"reqwest",
3867
+
"reqwest-websocket",
3868
+
"serde",
3869
+
"serde_json",
3870
+
"sha2",
3871
+
"signal-crypto",
3872
+
"thiserror 2.0.17",
3873
+
"tokio",
3874
+
"tracing",
3875
+
"tracing-futures",
3876
+
"url",
3877
+
"usernames",
3878
+
"uuid",
3879
+
"zkgroup",
3880
+
]
3881
+
3882
+
[[package]]
3883
+
name = "libsqlite3-sys"
3884
+
version = "0.30.1"
3885
+
source = "registry+https://github.com/rust-lang/crates.io-index"
3886
+
checksum = "2e99fb7a497b1e3339bc746195567ed8d3e24945ecd636e3619d20b9de9e9149"
3887
+
dependencies = [
3888
+
"pkg-config",
3889
+
"vcpkg",
3890
+
]
3891
+
3892
+
[[package]]
3893
+
name = "libz-rs-sys"
3894
+
version = "0.5.5"
3895
+
source = "registry+https://github.com/rust-lang/crates.io-index"
3896
+
checksum = "c10501e7805cee23da17c7790e59df2870c0d4043ec6d03f67d31e2b53e77415"
3897
+
dependencies = [
3898
+
"zlib-rs",
3899
+
]
3900
+
3901
+
[[package]]
3902
+
name = "linked-hash-map"
3903
+
version = "0.5.6"
3904
+
source = "registry+https://github.com/rust-lang/crates.io-index"
3905
+
checksum = "0717cef1bc8b636c6e1c1bbdefc09e6322da8a9321966e8928ef80d20f7f770f"
3906
+
3907
+
[[package]]
3908
+
name = "linux-raw-sys"
3909
+
version = "0.4.15"
3910
+
source = "registry+https://github.com/rust-lang/crates.io-index"
3911
+
checksum = "d26c52dbd32dccf2d10cac7725f8eae5296885fb5703b261f7d0a0739ec807ab"
3912
+
3913
+
[[package]]
3914
+
name = "linux-raw-sys"
3915
+
version = "0.11.0"
3916
+
source = "registry+https://github.com/rust-lang/crates.io-index"
3917
+
checksum = "df1d3c3b53da64cf5760482273a98e575c651a67eec7f77df96b5b642de8f039"
3918
+
3919
+
[[package]]
3920
+
name = "litemap"
3921
+
version = "0.8.1"
3922
+
source = "registry+https://github.com/rust-lang/crates.io-index"
3923
+
checksum = "6373607a59f0be73a39b6fe456b8192fcc3585f602af20751600e974dd455e77"
3924
+
3925
+
[[package]]
3926
+
name = "lock_api"
3927
+
version = "0.4.14"
3928
+
source = "registry+https://github.com/rust-lang/crates.io-index"
3929
+
checksum = "224399e74b87b5f3557511d98dff8b14089b3dadafcab6bb93eab67d3aace965"
3930
+
dependencies = [
3931
+
"scopeguard",
3932
+
]
3933
+
3934
+
[[package]]
3935
+
name = "log"
3936
+
version = "0.4.29"
3937
+
source = "registry+https://github.com/rust-lang/crates.io-index"
3938
+
checksum = "5e5032e24019045c762d3c0f28f5b6b8bbf38563a65908389bf7978758920897"
3939
+
3940
+
[[package]]
3941
+
name = "loom"
3942
+
version = "0.7.2"
3943
+
source = "registry+https://github.com/rust-lang/crates.io-index"
3944
+
checksum = "419e0dc8046cb947daa77eb95ae174acfbddb7673b4151f56d1eed8e93fbfaca"
3945
+
dependencies = [
3946
+
"cfg-if",
3947
+
"generator",
3948
+
"scoped-tls",
3949
+
"tracing",
3950
+
"tracing-subscriber",
3951
+
]
3952
+
3953
+
[[package]]
3954
+
name = "lru"
3955
+
version = "0.12.5"
3956
+
source = "registry+https://github.com/rust-lang/crates.io-index"
3957
+
checksum = "234cf4f4a04dc1f57e24b96cc0cd600cf2af460d4161ac5ecdd0af8e1f3b2a38"
3958
+
dependencies = [
3959
+
"hashbrown 0.15.5",
3960
+
]
3961
+
3962
+
[[package]]
3963
+
name = "lru-cache"
3964
+
version = "0.1.2"
3965
+
source = "registry+https://github.com/rust-lang/crates.io-index"
3966
+
checksum = "31e24f1ad8321ca0e8a1e0ac13f23cb668e6f5466c2c57319f6a5cf1cc8e3b1c"
3967
+
dependencies = [
3968
+
"linked-hash-map",
3969
+
]
3970
+
3971
+
[[package]]
3972
+
name = "lru-slab"
3973
+
version = "0.1.2"
3974
+
source = "registry+https://github.com/rust-lang/crates.io-index"
3975
+
checksum = "112b39cec0b298b6c1999fee3e31427f74f676e4cb9879ed1a121b43661a4154"
3976
+
3977
+
[[package]]
3978
+
name = "match-lookup"
3979
+
version = "0.1.1"
3980
+
source = "registry+https://github.com/rust-lang/crates.io-index"
3981
+
checksum = "1265724d8cb29dbbc2b0f06fffb8bf1a8c0cf73a78eede9ba73a4a66c52a981e"
3982
+
dependencies = [
3983
+
"proc-macro2",
3984
+
"quote",
3985
+
"syn 1.0.109",
3515
3986
]
3516
3987
3517
3988
[[package]]
···
3689
4160
"unsigned-varint 0.8.0",
3690
4161
]
3691
4162
4163
+
[[package]]
4164
+
name = "multimap"
4165
+
version = "0.10.1"
4166
+
source = "registry+https://github.com/rust-lang/crates.io-index"
4167
+
checksum = "1d87ecb2933e8aeadb3e3a02b828fed80a7528047e68b4f424523a0981a3a084"
4168
+
3692
4169
[[package]]
3693
4170
name = "n0-future"
3694
4171
version = "0.1.3"
···
3696
4173
checksum = "7bb0e5d99e681ab3c938842b96fcb41bf8a7bb4bfdb11ccbd653a7e83e06c794"
3697
4174
dependencies = [
3698
4175
"cfg_aliases",
3699
-
"derive_more",
4176
+
"derive_more 1.0.0",
3700
4177
"futures-buffered",
3701
4178
"futures-lite",
3702
4179
"futures-util",
···
3841
4318
"libc",
3842
4319
]
3843
4320
4321
+
[[package]]
4322
+
name = "num_enum"
4323
+
version = "0.7.6"
4324
+
source = "registry+https://github.com/rust-lang/crates.io-index"
4325
+
checksum = "5d0bca838442ec211fa11de3a8b0e0e8f3a4522575b5c4c06ed722e005036f26"
4326
+
dependencies = [
4327
+
"num_enum_derive",
4328
+
"rustversion",
4329
+
]
4330
+
4331
+
[[package]]
4332
+
name = "num_enum_derive"
4333
+
version = "0.7.6"
4334
+
source = "registry+https://github.com/rust-lang/crates.io-index"
4335
+
checksum = "680998035259dcfcafe653688bf2aa6d3e2dc05e98be6ab46afb089dc84f1df8"
4336
+
dependencies = [
4337
+
"proc-macro-crate",
4338
+
"proc-macro2",
4339
+
"quote",
4340
+
"syn 2.0.111",
4341
+
]
4342
+
3844
4343
[[package]]
3845
4344
name = "oid-registry"
3846
4345
version = "0.7.1"
···
3862
4361
source = "registry+https://github.com/rust-lang/crates.io-index"
3863
4362
checksum = "384b8ab6d37215f3c5301a95a4accb5d64aa607f1fcb26a11b5303878451b4fe"
3864
4363
4364
+
[[package]]
4365
+
name = "oncemutex"
4366
+
version = "0.1.1"
4367
+
source = "registry+https://github.com/rust-lang/crates.io-index"
4368
+
checksum = "44d11de466f4a3006fe8a5e7ec84e93b79c70cb992ae0aa0eb631ad2df8abfe2"
4369
+
3865
4370
[[package]]
3866
4371
name = "opaque-debug"
3867
4372
version = "0.3.1"
···
4014
4519
dependencies = [
4015
4520
"parse-display-derive",
4016
4521
"regex",
4017
-
"regex-syntax",
4522
+
"regex-syntax 0.8.8",
4018
4523
]
4019
4524
4020
4525
[[package]]
···
4026
4531
"proc-macro2",
4027
4532
"quote",
4028
4533
"regex",
4029
-
"regex-syntax",
4534
+
"regex-syntax 0.8.8",
4030
4535
"structmeta",
4031
4536
"syn 2.0.111",
4032
4537
]
4033
4538
4539
+
[[package]]
4540
+
name = "partial-default"
4541
+
version = "0.1.0"
4542
+
source = "registry+https://github.com/rust-lang/crates.io-index"
4543
+
checksum = "124dc3c21ffb6fb3a0562d129929a8a54998766ef7adc1ba09ddc467d092c14b"
4544
+
dependencies = [
4545
+
"partial-default-derive",
4546
+
]
4547
+
4548
+
[[package]]
4549
+
name = "partial-default-derive"
4550
+
version = "0.1.0"
4551
+
source = "registry+https://github.com/rust-lang/crates.io-index"
4552
+
checksum = "7459127d7a18cb202d418e4b7df1103ffd6d82a106e9b2091c250624c2ace70d"
4553
+
dependencies = [
4554
+
"proc-macro2",
4555
+
"quote",
4556
+
"syn 2.0.111",
4557
+
]
4558
+
4559
+
[[package]]
4560
+
name = "password-hash"
4561
+
version = "0.5.0"
4562
+
source = "registry+https://github.com/rust-lang/crates.io-index"
4563
+
checksum = "346f04948ba92c43e8469c1ee6736c7563d71012b17d40745260fe106aac2166"
4564
+
dependencies = [
4565
+
"base64ct",
4566
+
"rand_core 0.6.4",
4567
+
"subtle",
4568
+
]
4569
+
4034
4570
[[package]]
4035
4571
name = "pastey"
4036
4572
version = "0.1.1"
···
4062
4598
source = "registry+https://github.com/rust-lang/crates.io-index"
4063
4599
checksum = "9b4f627cb1b25917193a259e49bdad08f671f8d9708acfd5fe0a8c1455d87220"
4064
4600
4601
+
[[package]]
4602
+
name = "petgraph"
4603
+
version = "0.7.1"
4604
+
source = "registry+https://github.com/rust-lang/crates.io-index"
4605
+
checksum = "3672b37090dbd86368a4145bc067582552b29c27377cad4e0a306c97f9bd7772"
4606
+
dependencies = [
4607
+
"fixedbitset",
4608
+
"indexmap 2.12.1",
4609
+
]
4610
+
4611
+
[[package]]
4612
+
name = "phonenumber"
4613
+
version = "0.3.9+9.0.21"
4614
+
source = "registry+https://github.com/rust-lang/crates.io-index"
4615
+
checksum = "9114f9c1683dd09c5f4fa024c89fdad783eaae21d3d52dd23ddaaffa29ffb168"
4616
+
dependencies = [
4617
+
"either",
4618
+
"fnv",
4619
+
"nom",
4620
+
"once_cell",
4621
+
"postcard",
4622
+
"quick-xml",
4623
+
"regex",
4624
+
"regex-cache",
4625
+
"serde",
4626
+
"serde_derive",
4627
+
"strum",
4628
+
"thiserror 2.0.17",
4629
+
]
4630
+
4065
4631
[[package]]
4066
4632
name = "pin-project"
4067
4633
version = "1.1.10"
···
4144
4710
"miniz_oxide",
4145
4711
]
4146
4712
4713
+
[[package]]
4714
+
name = "poksho"
4715
+
version = "0.7.0"
4716
+
source = "git+https://github.com/signalapp/libsignal?tag=v0.87.4#38514bdc8acaaffbccd5c96515c68deb2019abe0"
4717
+
dependencies = [
4718
+
"curve25519-dalek",
4719
+
"hmac",
4720
+
"sha2",
4721
+
]
4722
+
4147
4723
[[package]]
4148
4724
name = "polyval"
4149
4725
version = "0.6.2"
···
4199
4775
"zerocopy",
4200
4776
]
4201
4777
4778
+
[[package]]
4779
+
name = "presage"
4780
+
version = "0.8.0-dev"
4781
+
source = "git+https://github.com/whisperfish/presage?rev=fe3ed54c4844ae51c3a9fa49cf80a7816a31a425#fe3ed54c4844ae51c3a9fa49cf80a7816a31a425"
4782
+
dependencies = [
4783
+
"base64 0.22.1",
4784
+
"bytes",
4785
+
"derive_more 2.1.1",
4786
+
"futures",
4787
+
"hex",
4788
+
"libsignal-service",
4789
+
"rand 0.9.2",
4790
+
"serde",
4791
+
"serde_json",
4792
+
"sha2",
4793
+
"thiserror 1.0.69",
4794
+
"tokio",
4795
+
"tracing",
4796
+
"url",
4797
+
]
4798
+
4202
4799
[[package]]
4203
4800
name = "prettyplease"
4204
4801
version = "0.2.37"
···
4218
4815
"elliptic-curve 0.13.8",
4219
4816
]
4220
4817
4818
+
[[package]]
4819
+
name = "proc-macro-crate"
4820
+
version = "3.5.0"
4821
+
source = "registry+https://github.com/rust-lang/crates.io-index"
4822
+
checksum = "e67ba7e9b2b56446f1d419b1d807906278ffa1a658a8a5d8a39dcb1f5a78614f"
4823
+
dependencies = [
4824
+
"toml_edit",
4825
+
]
4826
+
4221
4827
[[package]]
4222
4828
name = "proc-macro-error"
4223
4829
version = "1.0.4"
···
4242
4848
"version_check",
4243
4849
]
4244
4850
4851
+
[[package]]
4852
+
name = "proc-macro-error-attr2"
4853
+
version = "2.0.0"
4854
+
source = "registry+https://github.com/rust-lang/crates.io-index"
4855
+
checksum = "96de42df36bb9bba5542fe9f1a054b8cc87e172759a1868aa05c1f3acc89dfc5"
4856
+
dependencies = [
4857
+
"proc-macro2",
4858
+
"quote",
4859
+
]
4860
+
4861
+
[[package]]
4862
+
name = "proc-macro-error2"
4863
+
version = "2.0.1"
4864
+
source = "registry+https://github.com/rust-lang/crates.io-index"
4865
+
checksum = "11ec05c52be0a07b08061f7dd003e7d7092e0472bc731b4af7bb1ef876109802"
4866
+
dependencies = [
4867
+
"proc-macro-error-attr2",
4868
+
"proc-macro2",
4869
+
"quote",
4870
+
"syn 2.0.111",
4871
+
]
4872
+
4245
4873
[[package]]
4246
4874
name = "proc-macro2"
4247
4875
version = "1.0.103"
···
4264
4892
"yansi",
4265
4893
]
4266
4894
4895
+
[[package]]
4896
+
name = "prost"
4897
+
version = "0.13.5"
4898
+
source = "registry+https://github.com/rust-lang/crates.io-index"
4899
+
checksum = "2796faa41db3ec313a31f7624d9286acf277b52de526150b7e69f3debf891ee5"
4900
+
dependencies = [
4901
+
"bytes",
4902
+
"prost-derive 0.13.5",
4903
+
]
4904
+
4267
4905
[[package]]
4268
4906
name = "prost"
4269
4907
version = "0.14.1"
···
4271
4909
checksum = "7231bd9b3d3d33c86b58adbac74b5ec0ad9f496b19d22801d773636feaa95f3d"
4272
4910
dependencies = [
4273
4911
"bytes",
4274
-
"prost-derive",
4912
+
"prost-derive 0.14.1",
4913
+
]
4914
+
4915
+
[[package]]
4916
+
name = "prost-build"
4917
+
version = "0.13.5"
4918
+
source = "registry+https://github.com/rust-lang/crates.io-index"
4919
+
checksum = "be769465445e8c1474e9c5dac2018218498557af32d9ed057325ec9a41ae81bf"
4920
+
dependencies = [
4921
+
"heck 0.4.1",
4922
+
"itertools",
4923
+
"log",
4924
+
"multimap",
4925
+
"once_cell",
4926
+
"petgraph",
4927
+
"prettyplease",
4928
+
"prost 0.13.5",
4929
+
"prost-types 0.13.5",
4930
+
"regex",
4931
+
"syn 2.0.111",
4932
+
"tempfile",
4933
+
]
4934
+
4935
+
[[package]]
4936
+
name = "prost-build"
4937
+
version = "0.14.1"
4938
+
source = "registry+https://github.com/rust-lang/crates.io-index"
4939
+
checksum = "ac6c3320f9abac597dcbc668774ef006702672474aad53c6d596b62e487b40b1"
4940
+
dependencies = [
4941
+
"heck 0.4.1",
4942
+
"itertools",
4943
+
"log",
4944
+
"multimap",
4945
+
"once_cell",
4946
+
"petgraph",
4947
+
"prettyplease",
4948
+
"prost 0.14.1",
4949
+
"prost-types 0.14.1",
4950
+
"regex",
4951
+
"syn 2.0.111",
4952
+
"tempfile",
4953
+
]
4954
+
4955
+
[[package]]
4956
+
name = "prost-derive"
4957
+
version = "0.13.5"
4958
+
source = "registry+https://github.com/rust-lang/crates.io-index"
4959
+
checksum = "8a56d757972c98b346a9b766e3f02746cde6dd1cd1d1d563472929fdd74bec4d"
4960
+
dependencies = [
4961
+
"anyhow",
4962
+
"itertools",
4963
+
"proc-macro2",
4964
+
"quote",
4965
+
"syn 2.0.111",
4275
4966
]
4276
4967
4277
4968
[[package]]
···
4287
4978
"syn 2.0.111",
4288
4979
]
4289
4980
4981
+
[[package]]
4982
+
name = "prost-types"
4983
+
version = "0.13.5"
4984
+
source = "registry+https://github.com/rust-lang/crates.io-index"
4985
+
checksum = "52c2c1bf36ddb1a1c396b3601a3cec27c2462e45f07c386894ec3ccf5332bd16"
4986
+
dependencies = [
4987
+
"prost 0.13.5",
4988
+
]
4989
+
4290
4990
[[package]]
4291
4991
name = "prost-types"
4292
4992
version = "0.14.1"
4293
4993
source = "registry+https://github.com/rust-lang/crates.io-index"
4294
4994
checksum = "b9b4db3d6da204ed77bb26ba83b6122a73aeb2e87e25fbf7ad2e84c4ccbf8f72"
4295
4995
dependencies = [
4296
-
"prost",
4996
+
"prost 0.14.1",
4997
+
]
4998
+
4999
+
[[package]]
5000
+
name = "protobuf"
5001
+
version = "3.7.2"
5002
+
source = "registry+https://github.com/rust-lang/crates.io-index"
5003
+
checksum = "d65a1d4ddae7d8b5de68153b48f6aa3bba8cb002b243dbdbc55a5afbc98f99f4"
5004
+
dependencies = [
5005
+
"once_cell",
5006
+
"protobuf-support",
5007
+
"thiserror 1.0.69",
5008
+
]
5009
+
5010
+
[[package]]
5011
+
name = "protobuf-codegen"
5012
+
version = "3.7.2"
5013
+
source = "registry+https://github.com/rust-lang/crates.io-index"
5014
+
checksum = "5d3976825c0014bbd2f3b34f0001876604fe87e0c86cd8fa54251530f1544ace"
5015
+
dependencies = [
5016
+
"anyhow",
5017
+
"once_cell",
5018
+
"protobuf",
5019
+
"protobuf-parse",
5020
+
"regex",
5021
+
"tempfile",
5022
+
"thiserror 1.0.69",
5023
+
]
5024
+
5025
+
[[package]]
5026
+
name = "protobuf-parse"
5027
+
version = "3.7.2"
5028
+
source = "registry+https://github.com/rust-lang/crates.io-index"
5029
+
checksum = "b4aeaa1f2460f1d348eeaeed86aea999ce98c1bded6f089ff8514c9d9dbdc973"
5030
+
dependencies = [
5031
+
"anyhow",
5032
+
"indexmap 2.12.1",
5033
+
"log",
5034
+
"protobuf",
5035
+
"protobuf-support",
5036
+
"tempfile",
5037
+
"thiserror 1.0.69",
5038
+
"which",
5039
+
]
5040
+
5041
+
[[package]]
5042
+
name = "protobuf-support"
5043
+
version = "3.7.2"
5044
+
source = "registry+https://github.com/rust-lang/crates.io-index"
5045
+
checksum = "3e36c2f31e0a47f9280fb347ef5e461ffcd2c52dd520d8e216b52f93b0b0d7d6"
5046
+
dependencies = [
5047
+
"thiserror 1.0.69",
4297
5048
]
4298
5049
4299
5050
[[package]]
···
4343
5094
source = "registry+https://github.com/rust-lang/crates.io-index"
4344
5095
checksum = "a993555f31e5a609f617c12db6250dedcac1b0a85076912c436e6fc9b2c8e6a3"
4345
5096
5097
+
[[package]]
5098
+
name = "quick-xml"
5099
+
version = "0.38.4"
5100
+
source = "registry+https://github.com/rust-lang/crates.io-index"
5101
+
checksum = "b66c2058c55a409d601666cffe35f04333cf1013010882cec174a7467cd4e21c"
5102
+
dependencies = [
5103
+
"memchr",
5104
+
]
5105
+
4346
5106
[[package]]
4347
5107
name = "quinn"
4348
5108
version = "0.11.9"
···
4496
5256
"bitflags",
4497
5257
]
4498
5258
5259
+
[[package]]
5260
+
name = "rayon"
5261
+
version = "1.11.0"
5262
+
source = "registry+https://github.com/rust-lang/crates.io-index"
5263
+
checksum = "368f01d005bf8fd9b1206fb6fa653e6c4a81ceb1466406b81792d87c5677a58f"
5264
+
dependencies = [
5265
+
"either",
5266
+
"rayon-core",
5267
+
]
5268
+
5269
+
[[package]]
5270
+
name = "rayon-core"
5271
+
version = "1.13.0"
5272
+
source = "registry+https://github.com/rust-lang/crates.io-index"
5273
+
checksum = "22e18b0f0062d30d4230b2e85ff77fdfe4326feb054b9783a3460d8435c8ab91"
5274
+
dependencies = [
5275
+
"crossbeam-deque",
5276
+
"crossbeam-utils",
5277
+
]
5278
+
4499
5279
[[package]]
4500
5280
name = "redis"
4501
5281
version = "1.0.1"
···
4570
5350
"aho-corasick",
4571
5351
"memchr",
4572
5352
"regex-automata",
4573
-
"regex-syntax",
5353
+
"regex-syntax 0.8.8",
4574
5354
]
4575
5355
4576
5356
[[package]]
···
4581
5361
dependencies = [
4582
5362
"aho-corasick",
4583
5363
"memchr",
4584
-
"regex-syntax",
5364
+
"regex-syntax 0.8.8",
5365
+
]
5366
+
5367
+
[[package]]
5368
+
name = "regex-cache"
5369
+
version = "0.2.1"
5370
+
source = "registry+https://github.com/rust-lang/crates.io-index"
5371
+
checksum = "2f7b62d69743b8b94f353b6b7c3deb4c5582828328bcb8d5fedf214373808793"
5372
+
dependencies = [
5373
+
"lru-cache",
5374
+
"oncemutex",
5375
+
"regex",
5376
+
"regex-syntax 0.6.29",
4585
5377
]
4586
5378
4587
5379
[[package]]
4588
5380
name = "regex-lite"
4589
5381
version = "0.1.8"
4590
5382
source = "registry+https://github.com/rust-lang/crates.io-index"
4591
-
checksum = "8d942b98df5e658f56f20d592c7f868833fe38115e65c33003d8cd224b0155da"
5383
+
checksum = "8d942b98df5e658f56f20d592c7f868833fe38115e65c33003d8cd224b0155da"
5384
+
5385
+
[[package]]
5386
+
name = "regex-syntax"
5387
+
version = "0.6.29"
5388
+
source = "registry+https://github.com/rust-lang/crates.io-index"
5389
+
checksum = "f162c6dd7b008981e4d40210aca20b4bd0f9b60ca9271061b07f78537722f2e1"
4592
5390
4593
5391
[[package]]
4594
5392
name = "regex-syntax"
···
4606
5404
"bytes",
4607
5405
"encoding_rs",
4608
5406
"futures-core",
5407
+
"futures-util",
4609
5408
"h2 0.4.12",
4610
5409
"http 1.4.0",
4611
5410
"http-body 1.0.1",
···
4616
5415
"js-sys",
4617
5416
"log",
4618
5417
"mime",
5418
+
"mime_guess",
4619
5419
"percent-encoding",
4620
5420
"pin-project-lite",
4621
5421
"quinn",
···
4627
5427
"sync_wrapper",
4628
5428
"tokio",
4629
5429
"tokio-rustls 0.26.4",
5430
+
"tokio-util",
4630
5431
"tower",
4631
5432
"tower-http",
4632
5433
"tower-service",
4633
5434
"url",
4634
5435
"wasm-bindgen",
4635
5436
"wasm-bindgen-futures",
5437
+
"wasm-streams",
4636
5438
"web-sys",
4637
5439
"webpki-roots 1.0.4",
4638
5440
]
4639
5441
5442
+
[[package]]
5443
+
name = "reqwest-websocket"
5444
+
version = "0.4.4"
5445
+
source = "registry+https://github.com/rust-lang/crates.io-index"
5446
+
checksum = "f477f800f86d8f5c320e19d8b2b1ef0b1e773ea7c75eec6c7f442e7ec3f06d7e"
5447
+
dependencies = [
5448
+
"async-tungstenite",
5449
+
"futures-util",
5450
+
"reqwest",
5451
+
"serde",
5452
+
"serde_json",
5453
+
"thiserror 2.0.17",
5454
+
"tokio",
5455
+
"tokio-util",
5456
+
"tracing",
5457
+
"tungstenite 0.24.0",
5458
+
"web-sys",
5459
+
]
5460
+
4640
5461
[[package]]
4641
5462
name = "resolv-conf"
4642
5463
version = "0.7.6"
···
4722
5543
"nom",
4723
5544
]
4724
5545
5546
+
[[package]]
5547
+
name = "rustix"
5548
+
version = "0.38.44"
5549
+
source = "registry+https://github.com/rust-lang/crates.io-index"
5550
+
checksum = "fdb5bc1ae2baa591800df16c9ca78619bf65c0488b41b96ccec5d11220d8c154"
5551
+
dependencies = [
5552
+
"bitflags",
5553
+
"errno",
5554
+
"libc",
5555
+
"linux-raw-sys 0.4.15",
5556
+
"windows-sys 0.52.0",
5557
+
]
5558
+
4725
5559
[[package]]
4726
5560
name = "rustix"
4727
5561
version = "1.1.3"
···
4731
5565
"bitflags",
4732
5566
"errno",
4733
5567
"libc",
4734
-
"linux-raw-sys",
5568
+
"linux-raw-sys 0.11.0",
4735
5569
"windows-sys 0.61.2",
4736
5570
]
4737
5571
···
5134
5968
"cfg-if",
5135
5969
"cpufeatures",
5136
5970
"digest",
5971
+
"sha2-asm",
5972
+
]
5973
+
5974
+
[[package]]
5975
+
name = "sha2-asm"
5976
+
version = "0.6.4"
5977
+
source = "registry+https://github.com/rust-lang/crates.io-index"
5978
+
checksum = "b845214d6175804686b2bd482bcffe96651bb2d1200742b712003504a2dac1ab"
5979
+
dependencies = [
5980
+
"cc",
5137
5981
]
5138
5982
5139
5983
[[package]]
···
5151
5995
source = "registry+https://github.com/rust-lang/crates.io-index"
5152
5996
checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64"
5153
5997
5998
+
[[package]]
5999
+
name = "signal-crypto"
6000
+
version = "0.1.0"
6001
+
source = "git+https://github.com/signalapp/libsignal?tag=v0.87.4#38514bdc8acaaffbccd5c96515c68deb2019abe0"
6002
+
dependencies = [
6003
+
"aes",
6004
+
"cbc",
6005
+
"ctr",
6006
+
"derive_more 2.1.1",
6007
+
"displaydoc",
6008
+
"ghash",
6009
+
"hkdf",
6010
+
"hmac",
6011
+
"hpke-rs",
6012
+
"hpke-rs-crypto",
6013
+
"libsignal-core",
6014
+
"rand_chacha 0.9.0",
6015
+
"rand_core 0.9.3",
6016
+
"sha1",
6017
+
"sha2",
6018
+
"subtle",
6019
+
"thiserror 2.0.17",
6020
+
]
6021
+
5154
6022
[[package]]
5155
6023
name = "signal-hook-registry"
5156
6024
version = "1.4.7"
···
5249
6117
"windows-sys 0.60.2",
5250
6118
]
5251
6119
6120
+
[[package]]
6121
+
name = "sorted-vec"
6122
+
version = "0.8.10"
6123
+
source = "registry+https://github.com/rust-lang/crates.io-index"
6124
+
checksum = "19f58d7b0190c7f12df7e8be6b79767a0836059159811b869d5ab55721fe14d0"
6125
+
5252
6126
[[package]]
5253
6127
name = "spin"
5254
6128
version = "0.9.8"
···
5293
6167
"der 0.7.10",
5294
6168
]
5295
6169
6170
+
[[package]]
6171
+
name = "spqr"
6172
+
version = "1.4.0"
6173
+
source = "git+https://github.com/signalapp/SparsePostQuantumRatchet.git?tag=v1.4.0#d310c99c57a046549be205b9ce50d80dcbe5f3e4"
6174
+
dependencies = [
6175
+
"cpufeatures",
6176
+
"curve25519-dalek",
6177
+
"displaydoc",
6178
+
"hax-lib",
6179
+
"hkdf",
6180
+
"libcrux-hmac",
6181
+
"libcrux-ml-kem",
6182
+
"log",
6183
+
"num_enum",
6184
+
"prost 0.14.1",
6185
+
"prost-build 0.14.1",
6186
+
"rand 0.9.2",
6187
+
"rand_core 0.9.3",
6188
+
"sha2",
6189
+
"sorted-vec",
6190
+
"thiserror 2.0.17",
6191
+
]
6192
+
5296
6193
[[package]]
5297
6194
name = "sqlx"
5298
6195
version = "0.8.6"
···
5563
6460
"syn 2.0.111",
5564
6461
]
5565
6462
6463
+
[[package]]
6464
+
name = "strum"
6465
+
version = "0.27.2"
6466
+
source = "registry+https://github.com/rust-lang/crates.io-index"
6467
+
checksum = "af23d6f6c1a224baef9d3f61e287d2761385a5b88fdab4eb4c6f11aeb54c4bcf"
6468
+
dependencies = [
6469
+
"strum_macros",
6470
+
]
6471
+
6472
+
[[package]]
6473
+
name = "strum_macros"
6474
+
version = "0.27.2"
6475
+
source = "registry+https://github.com/rust-lang/crates.io-index"
6476
+
checksum = "7695ce3845ea4b33927c055a39dc438a45b059f7c1b3d91d38d10355fb8cbca7"
6477
+
dependencies = [
6478
+
"heck 0.5.0",
6479
+
"proc-macro2",
6480
+
"quote",
6481
+
"syn 2.0.111",
6482
+
]
6483
+
5566
6484
[[package]]
5567
6485
name = "subtle"
5568
6486
version = "2.6.1"
···
5632
6550
"libc",
5633
6551
]
5634
6552
6553
+
[[package]]
6554
+
name = "tempfile"
6555
+
version = "3.25.0"
6556
+
source = "registry+https://github.com/rust-lang/crates.io-index"
6557
+
checksum = "0136791f7c95b1f6dd99f9cc786b91bb81c3800b639b3478e561ddb7be95e5f1"
6558
+
dependencies = [
6559
+
"fastrand",
6560
+
"getrandom 0.3.4",
6561
+
"once_cell",
6562
+
"rustix 1.1.3",
6563
+
"windows-sys 0.52.0",
6564
+
]
6565
+
5635
6566
[[package]]
5636
6567
name = "testcontainers"
5637
6568
version = "0.26.2"
···
5846
6777
"rustls-pki-types",
5847
6778
"tokio",
5848
6779
"tokio-rustls 0.26.4",
5849
-
"tungstenite",
6780
+
"tungstenite 0.28.0",
5850
6781
"webpki-roots 0.26.11",
5851
6782
]
5852
6783
···
5858
6789
dependencies = [
5859
6790
"bytes",
5860
6791
"futures-core",
6792
+
"futures-io",
5861
6793
"futures-sink",
5862
6794
"futures-util",
5863
6795
"pin-project-lite",
···
5873
6805
"indexmap 2.12.1",
5874
6806
"serde_core",
5875
6807
"serde_spanned",
5876
-
"toml_datetime",
6808
+
"toml_datetime 0.7.5+spec-1.1.0",
5877
6809
"toml_parser",
5878
6810
"toml_writer",
5879
6811
"winnow",
···
5888
6820
"serde_core",
5889
6821
]
5890
6822
6823
+
[[package]]
6824
+
name = "toml_datetime"
6825
+
version = "1.0.1+spec-1.1.0"
6826
+
source = "registry+https://github.com/rust-lang/crates.io-index"
6827
+
checksum = "9b320e741db58cac564e26c607d3cc1fdc4a88fd36c879568c07856ed83ff3e9"
6828
+
dependencies = [
6829
+
"serde_core",
6830
+
]
6831
+
6832
+
[[package]]
6833
+
name = "toml_edit"
6834
+
version = "0.25.0+spec-1.1.0"
6835
+
source = "registry+https://github.com/rust-lang/crates.io-index"
6836
+
checksum = "caee3f6e1c6f2025affe9191e6e6f66ade10b48f36b1a1b3cd92dfe405ffd260"
6837
+
dependencies = [
6838
+
"indexmap 2.12.1",
6839
+
"toml_datetime 1.0.1+spec-1.1.0",
6840
+
"toml_parser",
6841
+
"winnow",
6842
+
]
6843
+
5891
6844
[[package]]
5892
6845
name = "toml_parser"
5893
6846
version = "1.0.7+spec-1.1.0"
···
5939
6892
checksum = "66bd50ad6ce1252d87ef024b3d64fe4c3cf54a86fb9ef4c631fdd0ded7aeaa67"
5940
6893
dependencies = [
5941
6894
"bytes",
5942
-
"prost",
6895
+
"prost 0.14.1",
5943
6896
"tonic",
5944
6897
]
5945
6898
···
6052
7005
"valuable",
6053
7006
]
6054
7007
7008
+
[[package]]
7009
+
name = "tracing-futures"
7010
+
version = "0.2.5"
7011
+
source = "registry+https://github.com/rust-lang/crates.io-index"
7012
+
checksum = "97d095ae15e245a057c8e8451bab9b3ee1e1f68e9ba2b4fbc18d0ac5237835f2"
7013
+
dependencies = [
7014
+
"pin-project",
7015
+
"tracing",
7016
+
]
7017
+
6055
7018
[[package]]
6056
7019
name = "tracing-log"
6057
7020
version = "0.2.0"
···
6094
7057
6095
7058
[[package]]
6096
7059
name = "tranquil-api"
6097
-
version = "0.4.6"
7060
+
version = "0.4.7"
6098
7061
dependencies = [
6099
7062
"anyhow",
6100
7063
"axum",
···
6142
7105
6143
7106
[[package]]
6144
7107
name = "tranquil-auth"
6145
-
version = "0.4.6"
7108
+
version = "0.4.7"
6146
7109
dependencies = [
6147
7110
"anyhow",
6148
7111
"base32",
···
6165
7128
6166
7129
[[package]]
6167
7130
name = "tranquil-cache"
6168
-
version = "0.4.6"
7131
+
version = "0.4.7"
6169
7132
dependencies = [
6170
7133
"async-trait",
6171
7134
"base64 0.22.1",
···
6179
7142
6180
7143
[[package]]
6181
7144
name = "tranquil-comms"
6182
-
version = "0.4.6"
7145
+
version = "0.4.7"
6183
7146
dependencies = [
6184
7147
"async-trait",
6185
7148
"base64 0.22.1",
···
6194
7157
6195
7158
[[package]]
6196
7159
name = "tranquil-config"
6197
-
version = "0.4.6"
7160
+
version = "0.4.7"
6198
7161
dependencies = [
6199
7162
"confique",
6200
7163
"serde",
···
6202
7165
6203
7166
[[package]]
6204
7167
name = "tranquil-crypto"
6205
-
version = "0.4.6"
7168
+
version = "0.4.7"
6206
7169
dependencies = [
6207
7170
"aes-gcm",
6208
7171
"base64 0.22.1",
···
6218
7181
6219
7182
[[package]]
6220
7183
name = "tranquil-db"
6221
-
version = "0.4.6"
7184
+
version = "0.4.7"
6222
7185
dependencies = [
6223
7186
"async-trait",
6224
7187
"chrono",
···
6235
7198
6236
7199
[[package]]
6237
7200
name = "tranquil-db-traits"
6238
-
version = "0.4.6"
7201
+
version = "0.4.7"
6239
7202
dependencies = [
6240
7203
"async-trait",
6241
7204
"base64 0.22.1",
···
6251
7214
6252
7215
[[package]]
6253
7216
name = "tranquil-infra"
6254
-
version = "0.4.6"
7217
+
version = "0.4.7"
6255
7218
dependencies = [
6256
7219
"async-trait",
6257
7220
"bytes",
···
6262
7225
6263
7226
[[package]]
6264
7227
name = "tranquil-lexicon"
6265
-
version = "0.4.6"
7228
+
version = "0.4.7"
6266
7229
dependencies = [
6267
7230
"chrono",
6268
7231
"hickory-resolver",
···
6280
7243
6281
7244
[[package]]
6282
7245
name = "tranquil-oauth"
6283
-
version = "0.4.6"
7246
+
version = "0.4.7"
6284
7247
dependencies = [
6285
7248
"anyhow",
6286
7249
"axum",
···
6303
7266
6304
7267
[[package]]
6305
7268
name = "tranquil-oauth-server"
6306
-
version = "0.4.6"
7269
+
version = "0.4.7"
6307
7270
dependencies = [
6308
7271
"axum",
6309
7272
"base64 0.22.1",
···
6336
7299
6337
7300
[[package]]
6338
7301
name = "tranquil-pds"
6339
-
version = "0.4.6"
7302
+
version = "0.4.7"
6340
7303
dependencies = [
6341
7304
"aes-gcm",
6342
7305
"anyhow",
···
6424
7387
6425
7388
[[package]]
6426
7389
name = "tranquil-repo"
6427
-
version = "0.4.6"
7390
+
version = "0.4.7"
6428
7391
dependencies = [
6429
7392
"bytes",
6430
7393
"cid",
···
6436
7399
6437
7400
[[package]]
6438
7401
name = "tranquil-ripple"
6439
-
version = "0.4.6"
7402
+
version = "0.4.7"
6440
7403
dependencies = [
6441
7404
"async-trait",
6442
7405
"backon",
6443
-
"bincode",
7406
+
"bincode 2.0.1",
6444
7407
"bytes",
6445
7408
"foca",
6446
7409
"futures",
···
6461
7424
6462
7425
[[package]]
6463
7426
name = "tranquil-scopes"
6464
-
version = "0.4.6"
7427
+
version = "0.4.7"
6465
7428
dependencies = [
6466
7429
"axum",
6467
7430
"futures",
···
6477
7440
6478
7441
[[package]]
6479
7442
name = "tranquil-server"
6480
-
version = "0.4.6"
7443
+
version = "0.4.7"
6481
7444
dependencies = [
6482
7445
"axum",
6483
7446
"clap",
···
6495
7458
"tranquil-sync",
6496
7459
]
6497
7460
7461
+
[[package]]
7462
+
name = "tranquil-signal"
7463
+
version = "0.4.7"
7464
+
dependencies = [
7465
+
"async-trait",
7466
+
"chrono",
7467
+
"futures",
7468
+
"presage",
7469
+
"rand 0.9.2",
7470
+
"serde",
7471
+
"serde_json",
7472
+
"sqlx",
7473
+
"thiserror 2.0.17",
7474
+
"tokio",
7475
+
"tokio-util",
7476
+
"tracing",
7477
+
"url",
7478
+
"uuid",
7479
+
]
7480
+
6498
7481
[[package]]
6499
7482
name = "tranquil-storage"
6500
-
version = "0.4.6"
7483
+
version = "0.4.7"
6501
7484
dependencies = [
6502
7485
"async-trait",
6503
7486
"aws-config",
···
6514
7497
6515
7498
[[package]]
6516
7499
name = "tranquil-sync"
6517
-
version = "0.4.6"
7500
+
version = "0.4.7"
6518
7501
dependencies = [
6519
7502
"anyhow",
6520
7503
"axum",
···
6536
7519
6537
7520
[[package]]
6538
7521
name = "tranquil-types"
6539
-
version = "0.4.6"
7522
+
version = "0.4.7"
6540
7523
dependencies = [
6541
7524
"chrono",
6542
7525
"cid",
···
6553
7536
source = "registry+https://github.com/rust-lang/crates.io-index"
6554
7537
checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b"
6555
7538
7539
+
[[package]]
7540
+
name = "tungstenite"
7541
+
version = "0.24.0"
7542
+
source = "registry+https://github.com/rust-lang/crates.io-index"
7543
+
checksum = "18e5b8366ee7a95b16d32197d0b2604b43a0be89dc5fac9f8e96ccafbaedda8a"
7544
+
dependencies = [
7545
+
"byteorder",
7546
+
"bytes",
7547
+
"data-encoding",
7548
+
"http 1.4.0",
7549
+
"httparse",
7550
+
"log",
7551
+
"rand 0.8.5",
7552
+
"sha1",
7553
+
"thiserror 1.0.69",
7554
+
"utf-8",
7555
+
]
7556
+
6556
7557
[[package]]
6557
7558
name = "tungstenite"
6558
7559
version = "0.28.0"
···
6709
7710
source = "registry+https://github.com/rust-lang/crates.io-index"
6710
7711
checksum = "daf8dba3b7eb870caf1ddeed7bc9d2a049f3cfdfae7cb521b087cc33ae4c49da"
6711
7712
7713
+
[[package]]
7714
+
name = "usernames"
7715
+
version = "0.1.0"
7716
+
source = "git+https://github.com/signalapp/libsignal?tag=v0.87.4#38514bdc8acaaffbccd5c96515c68deb2019abe0"
7717
+
dependencies = [
7718
+
"curve25519-dalek",
7719
+
"displaydoc",
7720
+
"hkdf",
7721
+
"hmac",
7722
+
"log",
7723
+
"poksho",
7724
+
"prost 0.14.1",
7725
+
"prost-build 0.14.1",
7726
+
"rand 0.9.2",
7727
+
"sha2",
7728
+
"signal-crypto",
7729
+
"subtle",
7730
+
"thiserror 2.0.17",
7731
+
]
7732
+
6712
7733
[[package]]
6713
7734
name = "utf-8"
6714
7735
version = "0.7.6"
···
6859
7880
"unicode-ident",
6860
7881
]
6861
7882
7883
+
[[package]]
7884
+
name = "wasm-streams"
7885
+
version = "0.4.2"
7886
+
source = "registry+https://github.com/rust-lang/crates.io-index"
7887
+
checksum = "15053d8d85c7eccdbefef60f06769760a563c7f0a9d6902a13d35c7800b0ad65"
7888
+
dependencies = [
7889
+
"futures-util",
7890
+
"js-sys",
7891
+
"wasm-bindgen",
7892
+
"wasm-bindgen-futures",
7893
+
"web-sys",
7894
+
]
7895
+
6862
7896
[[package]]
6863
7897
name = "web-sys"
6864
7898
version = "0.3.83"
···
6971
8005
source = "registry+https://github.com/rust-lang/crates.io-index"
6972
8006
checksum = "a28ac98ddc8b9274cb41bb4d9d4d5c425b6020c50c46f25559911905610b4a88"
6973
8007
8008
+
[[package]]
8009
+
name = "which"
8010
+
version = "4.4.2"
8011
+
source = "registry+https://github.com/rust-lang/crates.io-index"
8012
+
checksum = "87ba24419a2078cd2b0f2ede2691b6c66d8e47836da3b6db8265ebad47afbfc7"
8013
+
dependencies = [
8014
+
"either",
8015
+
"home",
8016
+
"once_cell",
8017
+
"rustix 0.38.44",
8018
+
]
8019
+
6974
8020
[[package]]
6975
8021
name = "whoami"
6976
8022
version = "1.6.1"
···
7306
8352
version = "0.7.14"
7307
8353
source = "registry+https://github.com/rust-lang/crates.io-index"
7308
8354
checksum = "5a5364e9d77fcdeeaa6062ced926ee3381faa2ee02d3eb83a5c27a8825540829"
8355
+
dependencies = [
8356
+
"memchr",
8357
+
]
7309
8358
7310
8359
[[package]]
7311
8360
name = "winreg"
···
7352
8401
source = "registry+https://github.com/rust-lang/crates.io-index"
7353
8402
checksum = "9edde0db4769d2dc68579893f2306b26c6ecfbe0ef499b013d731b7b9247e0b9"
7354
8403
8404
+
[[package]]
8405
+
name = "x25519-dalek"
8406
+
version = "2.0.1"
8407
+
source = "registry+https://github.com/rust-lang/crates.io-index"
8408
+
checksum = "c7e468321c81fb07fa7f4c636c3972b9100f0346e5b6a9f2bd0603a52f7ed277"
8409
+
dependencies = [
8410
+
"curve25519-dalek",
8411
+
"rand_core 0.6.4",
8412
+
"serde",
8413
+
"zeroize",
8414
+
]
8415
+
7355
8416
[[package]]
7356
8417
name = "x509-parser"
7357
8418
version = "0.16.0"
···
7376
8437
checksum = "32e45ad4206f6d2479085147f02bc2ef834ac85886624a23575ae137c8aa8156"
7377
8438
dependencies = [
7378
8439
"libc",
7379
-
"rustix",
8440
+
"rustix 1.1.3",
7380
8441
]
7381
8442
7382
8443
[[package]]
···
7466
8527
version = "1.8.2"
7467
8528
source = "registry+https://github.com/rust-lang/crates.io-index"
7468
8529
checksum = "b97154e67e32c85465826e8bcc1c59429aaaf107c1e4a9e53c8d8ccd5eff88d0"
8530
+
dependencies = [
8531
+
"zeroize_derive",
8532
+
]
8533
+
8534
+
[[package]]
8535
+
name = "zeroize_derive"
8536
+
version = "1.4.3"
8537
+
source = "registry+https://github.com/rust-lang/crates.io-index"
8538
+
checksum = "85a5b4158499876c763cb03bc4e49185d3cccbabb15b33c627f7884f43db852e"
8539
+
dependencies = [
8540
+
"proc-macro2",
8541
+
"quote",
8542
+
"syn 2.0.111",
8543
+
]
7469
8544
7470
8545
[[package]]
7471
8546
name = "zerotrie"
···
7514
8589
"zopfli",
7515
8590
]
7516
8591
8592
+
[[package]]
8593
+
name = "zkcredential"
8594
+
version = "0.1.0"
8595
+
source = "git+https://github.com/signalapp/libsignal?tag=v0.87.4#38514bdc8acaaffbccd5c96515c68deb2019abe0"
8596
+
dependencies = [
8597
+
"cfg-if",
8598
+
"curve25519-dalek",
8599
+
"derive-where",
8600
+
"displaydoc",
8601
+
"partial-default",
8602
+
"poksho",
8603
+
"rayon",
8604
+
"serde",
8605
+
"sha2",
8606
+
"subtle",
8607
+
"thiserror 2.0.17",
8608
+
]
8609
+
8610
+
[[package]]
8611
+
name = "zkgroup"
8612
+
version = "0.9.0"
8613
+
source = "git+https://github.com/signalapp/libsignal?tag=v0.87.4#38514bdc8acaaffbccd5c96515c68deb2019abe0"
8614
+
dependencies = [
8615
+
"aes",
8616
+
"aes-gcm-siv",
8617
+
"bincode 1.3.3",
8618
+
"const-str 1.1.0",
8619
+
"curve25519-dalek",
8620
+
"derive-where",
8621
+
"derive_more 2.1.1",
8622
+
"displaydoc",
8623
+
"hex",
8624
+
"hkdf",
8625
+
"libsignal-account-keys",
8626
+
"libsignal-core",
8627
+
"partial-default",
8628
+
"poksho",
8629
+
"rand 0.9.2",
8630
+
"rayon",
8631
+
"serde",
8632
+
"sha2",
8633
+
"static_assertions",
8634
+
"subtle",
8635
+
"thiserror 2.0.17",
8636
+
"uuid",
8637
+
"zkcredential",
8638
+
]
8639
+
7517
8640
[[package]]
7518
8641
name = "zlib-rs"
7519
8642
version = "0.5.5"
+9
-1
Cargo.toml
+9
-1
Cargo.toml
···
21
21
"crates/tranquil-oauth-server",
22
22
"crates/tranquil-api",
23
23
"crates/tranquil-lexicon",
24
+
"crates/tranquil-signal",
24
25
]
25
26
26
27
[workspace.package]
27
-
version = "0.4.6"
28
+
version = "0.4.7"
28
29
edition = "2024"
29
30
license = "AGPL-3.0-or-later"
30
31
···
49
50
tranquil-sync = { path = "crates/tranquil-sync" }
50
51
tranquil-oauth-server = { path = "crates/tranquil-oauth-server" }
51
52
tranquil-api = { path = "crates/tranquil-api" }
53
+
tranquil-signal = { path = "crates/tranquil-signal" }
54
+
55
+
presage = { git = "https://github.com/whisperfish/presage", rev = "fe3ed54c4844ae51c3a9fa49cf80a7816a31a425", default-features = false }
52
56
53
57
unicode-segmentation = "1"
54
58
···
81
85
hmac = "0.12"
82
86
http = "1.4"
83
87
image = { version = "0.25", default-features = false, features = ["jpeg", "png", "gif", "webp"] }
88
+
qrcodegen = "1.8"
84
89
infer = "0.19"
85
90
ipld-core = "0.4"
86
91
iroh-car = "0.5"
···
129
134
testcontainers-modules = { version = "0.14", features = ["postgres"] }
130
135
wiremock = "0.6"
131
136
137
+
[patch.crates-io]
138
+
curve25519-dalek = { git = "https://github.com/signalapp/curve25519-dalek", tag = "signal-curve25519-4.1.3" }
139
+
132
140
[profile.release]
133
141
lto = "fat"
134
142
strip = true
+23
crates/tranquil-signal/Cargo.toml
+23
crates/tranquil-signal/Cargo.toml
···
1
+
[package]
2
+
name = "tranquil-signal"
3
+
version.workspace = true
4
+
edition.workspace = true
5
+
license.workspace = true
6
+
7
+
[dependencies]
8
+
presage = { workspace = true }
9
+
async-trait = { workspace = true }
10
+
chrono = { workspace = true }
11
+
sqlx = { workspace = true }
12
+
tracing = { workspace = true }
13
+
tokio = { workspace = true }
14
+
tokio-util = { workspace = true }
15
+
futures = { workspace = true }
16
+
serde = { workspace = true }
17
+
serde_json = { workspace = true }
18
+
url = "2.5"
19
+
uuid = { workspace = true }
20
+
thiserror = { workspace = true }
21
+
22
+
[dev-dependencies]
23
+
rand = "0.9"
+1177
crates/tranquil-signal/src/store.rs
+1177
crates/tranquil-signal/src/store.rs
···
1
+
use std::ops::RangeBounds;
2
+
3
+
use async_trait::async_trait;
4
+
use presage::{
5
+
AvatarBytes,
6
+
libsignal_service::{
7
+
Profile,
8
+
pre_keys::{KyberPreKeyStoreExt, PreKeysStore},
9
+
prelude::{Content, MasterKey, ProfileKey, SessionStoreExt, Uuid},
10
+
protocol::{
11
+
CiphertextMessageType, DeviceId, Direction, GenericSignedPreKey, IdentityChange,
12
+
IdentityKey, IdentityKeyPair, IdentityKeyStore, KyberPreKeyId, KyberPreKeyRecord,
13
+
KyberPreKeyStore, PreKeyId, PreKeyRecord, PreKeyStore, ProtocolAddress, ProtocolStore,
14
+
PublicKey, SenderCertificate, SenderKeyRecord, SenderKeyStore, ServiceId,
15
+
SessionRecord, SessionStore, SignalProtocolError, SignedPreKeyId, SignedPreKeyRecord,
16
+
SignedPreKeyStore,
17
+
},
18
+
push_service::DEFAULT_DEVICE_ID,
19
+
zkgroup::GroupMasterKeyBytes,
20
+
},
21
+
manager::RegistrationData,
22
+
model::{contacts::Contact, groups::Group},
23
+
store::{ContentsStore, StateStore, StickerPack, Store, Thread},
24
+
};
25
+
use sqlx::PgPool;
26
+
use tracing::warn;
27
+
28
+
#[derive(Debug, Clone)]
29
+
pub struct PgSignalStore {
30
+
pub db: PgPool,
31
+
}
32
+
33
+
impl PgSignalStore {
34
+
pub fn new(db: PgPool) -> Self {
35
+
Self { db }
36
+
}
37
+
38
+
pub async fn is_linked(&self) -> Result<bool, PgStoreError> {
39
+
let row = sqlx::query!("SELECT value FROM signal_kv WHERE key = 'registration'")
40
+
.fetch_optional(&self.db)
41
+
.await?;
42
+
Ok(row.is_some())
43
+
}
44
+
45
+
async fn set_identity_key_pair(
46
+
&self,
47
+
identity: IdentityType,
48
+
key_pair: IdentityKeyPair,
49
+
) -> Result<(), PgStoreError> {
50
+
let key = identity.identity_key_pair_key();
51
+
let value = key_pair.serialize().to_vec();
52
+
sqlx::query!(
53
+
"INSERT INTO signal_kv (key, value) VALUES ($1, $2)
54
+
ON CONFLICT (key) DO UPDATE SET value = $2",
55
+
key,
56
+
&value,
57
+
)
58
+
.execute(&self.db)
59
+
.await?;
60
+
Ok(())
61
+
}
62
+
63
+
async fn clear_protocol_tables(
64
+
tx: &mut sqlx::Transaction<'_, sqlx::Postgres>,
65
+
) -> Result<(), PgStoreError> {
66
+
sqlx::query!("DELETE FROM signal_base_keys_seen")
67
+
.execute(&mut **tx)
68
+
.await?;
69
+
sqlx::query!("DELETE FROM signal_sender_keys")
70
+
.execute(&mut **tx)
71
+
.await?;
72
+
sqlx::query!("DELETE FROM signal_kyber_pre_keys")
73
+
.execute(&mut **tx)
74
+
.await?;
75
+
sqlx::query!("DELETE FROM signal_signed_pre_keys")
76
+
.execute(&mut **tx)
77
+
.await?;
78
+
sqlx::query!("DELETE FROM signal_pre_keys")
79
+
.execute(&mut **tx)
80
+
.await?;
81
+
sqlx::query!("DELETE FROM signal_identities")
82
+
.execute(&mut **tx)
83
+
.await?;
84
+
sqlx::query!("DELETE FROM signal_sessions")
85
+
.execute(&mut **tx)
86
+
.await?;
87
+
Ok(())
88
+
}
89
+
90
+
pub async fn clear_all(&self) -> Result<(), PgStoreError> {
91
+
let mut tx = self.db.begin().await?;
92
+
Self::clear_protocol_tables(&mut tx).await?;
93
+
sqlx::query!("DELETE FROM signal_profile_keys")
94
+
.execute(&mut *tx)
95
+
.await?;
96
+
sqlx::query!("DELETE FROM signal_kv")
97
+
.execute(&mut *tx)
98
+
.await?;
99
+
tx.commit().await?;
100
+
Ok(())
101
+
}
102
+
}
103
+
104
+
#[derive(Debug, Clone)]
105
+
pub struct PgProtocolStore {
106
+
store: PgSignalStore,
107
+
identity: IdentityType,
108
+
}
109
+
110
+
impl PgProtocolStore {
111
+
pub(crate) fn new(store: PgSignalStore, identity: IdentityType) -> Self {
112
+
Self { store, identity }
113
+
}
114
+
}
115
+
116
+
fn next_id_from_max(max_id: Option<i32>) -> Result<u32, SignalProtocolError> {
117
+
match max_id {
118
+
None => Ok(1),
119
+
Some(id) => {
120
+
let current = i32_to_u32(id)?;
121
+
current.checked_add(1).ok_or_else(|| {
122
+
SignalProtocolError::InvalidState(
123
+
"pre key id space exhausted",
124
+
format!("max id {current} has no successor"),
125
+
)
126
+
})
127
+
}
128
+
}
129
+
}
130
+
131
+
#[derive(Debug, Clone, Copy)]
132
+
pub enum IdentityType {
133
+
Aci,
134
+
Pni,
135
+
}
136
+
137
+
impl IdentityType {
138
+
fn as_str(&self) -> &'static str {
139
+
match self {
140
+
Self::Aci => "aci",
141
+
Self::Pni => "pni",
142
+
}
143
+
}
144
+
145
+
fn identity_key_pair_key(&self) -> &'static str {
146
+
match self {
147
+
Self::Aci => "identity_keypair_aci",
148
+
Self::Pni => "identity_keypair_pni",
149
+
}
150
+
}
151
+
}
152
+
153
+
#[derive(Debug, thiserror::Error)]
154
+
pub enum PgStoreError {
155
+
#[error("sqlx: {0}")]
156
+
Sqlx(#[from] sqlx::Error),
157
+
#[error("json: {0}")]
158
+
Json(#[from] serde_json::Error),
159
+
#[error("protocol: {0}")]
160
+
Protocol(#[from] SignalProtocolError),
161
+
#[error("invalid format")]
162
+
InvalidFormat,
163
+
}
164
+
165
+
impl presage::store::StoreError for PgStoreError {}
166
+
167
+
fn u32_to_i32(val: u32) -> Result<i32, SignalProtocolError> {
168
+
i32::try_from(val).map_err(|_| {
169
+
SignalProtocolError::InvalidState("id overflow", format!("{val} exceeds i32::MAX"))
170
+
})
171
+
}
172
+
173
+
fn i32_to_u32(val: i32) -> Result<u32, SignalProtocolError> {
174
+
u32::try_from(val)
175
+
.map_err(|_| SignalProtocolError::InvalidState("negative id", format!("{val} is negative")))
176
+
}
177
+
178
+
trait IntoProtocolError<T> {
179
+
fn into_protocol_error(self) -> Result<T, SignalProtocolError>;
180
+
}
181
+
182
+
impl<T> IntoProtocolError<T> for Result<T, sqlx::Error> {
183
+
fn into_protocol_error(self) -> Result<T, SignalProtocolError> {
184
+
self.map_err(|e| SignalProtocolError::InvalidState("sqlx", e.to_string()))
185
+
}
186
+
}
187
+
188
+
impl<T> IntoProtocolError<T> for Result<T, PgStoreError> {
189
+
fn into_protocol_error(self) -> Result<T, SignalProtocolError> {
190
+
self.map_err(|e| SignalProtocolError::InvalidState("store", e.to_string()))
191
+
}
192
+
}
193
+
194
+
impl Store for PgSignalStore {
195
+
type Error = PgStoreError;
196
+
type AciStore = PgProtocolStore;
197
+
type PniStore = PgProtocolStore;
198
+
199
+
async fn clear(&mut self) -> Result<(), PgStoreError> {
200
+
self.clear_all().await
201
+
}
202
+
203
+
fn aci_protocol_store(&self) -> Self::AciStore {
204
+
PgProtocolStore::new(self.clone(), IdentityType::Aci)
205
+
}
206
+
207
+
fn pni_protocol_store(&self) -> Self::PniStore {
208
+
PgProtocolStore::new(self.clone(), IdentityType::Pni)
209
+
}
210
+
}
211
+
212
+
impl StateStore for PgSignalStore {
213
+
type StateStoreError = PgStoreError;
214
+
215
+
async fn load_registration_data(&self) -> Result<Option<RegistrationData>, PgStoreError> {
216
+
sqlx::query_scalar!("SELECT value FROM signal_kv WHERE key = 'registration'")
217
+
.fetch_optional(&self.db)
218
+
.await?
219
+
.map(|value| serde_json::from_slice(&value))
220
+
.transpose()
221
+
.map_err(From::from)
222
+
}
223
+
224
+
async fn save_registration_data(
225
+
&mut self,
226
+
state: &RegistrationData,
227
+
) -> Result<(), PgStoreError> {
228
+
let value = serde_json::to_vec(state)?;
229
+
sqlx::query!(
230
+
"INSERT INTO signal_kv (key, value) VALUES ('registration', $1)
231
+
ON CONFLICT (key) DO UPDATE SET value = $1",
232
+
&value,
233
+
)
234
+
.execute(&self.db)
235
+
.await?;
236
+
Ok(())
237
+
}
238
+
239
+
async fn is_registered(&self) -> bool {
240
+
self.load_registration_data().await.ok().flatten().is_some()
241
+
}
242
+
243
+
async fn clear_registration(&mut self) -> Result<(), PgStoreError> {
244
+
let mut tx = self.db.begin().await?;
245
+
sqlx::query!("DELETE FROM signal_kv WHERE key = 'registration'")
246
+
.execute(&mut *tx)
247
+
.await?;
248
+
Self::clear_protocol_tables(&mut tx).await?;
249
+
tx.commit().await?;
250
+
Ok(())
251
+
}
252
+
253
+
async fn set_aci_identity_key_pair(
254
+
&self,
255
+
key_pair: IdentityKeyPair,
256
+
) -> Result<(), PgStoreError> {
257
+
self.set_identity_key_pair(IdentityType::Aci, key_pair)
258
+
.await
259
+
}
260
+
261
+
async fn set_pni_identity_key_pair(
262
+
&self,
263
+
key_pair: IdentityKeyPair,
264
+
) -> Result<(), PgStoreError> {
265
+
self.set_identity_key_pair(IdentityType::Pni, key_pair)
266
+
.await
267
+
}
268
+
269
+
async fn sender_certificate(&self) -> Result<Option<SenderCertificate>, PgStoreError> {
270
+
sqlx::query_scalar!("SELECT value FROM signal_kv WHERE key = 'sender_certificate' LIMIT 1")
271
+
.fetch_optional(&self.db)
272
+
.await?
273
+
.map(|value| SenderCertificate::deserialize(&value))
274
+
.transpose()
275
+
.map_err(From::from)
276
+
}
277
+
278
+
async fn save_sender_certificate(
279
+
&self,
280
+
certificate: &SenderCertificate,
281
+
) -> Result<(), PgStoreError> {
282
+
let value = certificate.serialized()?.to_vec();
283
+
sqlx::query!(
284
+
"INSERT INTO signal_kv (key, value) VALUES ('sender_certificate', $1)
285
+
ON CONFLICT (key) DO UPDATE SET value = $1",
286
+
&value,
287
+
)
288
+
.execute(&self.db)
289
+
.await?;
290
+
Ok(())
291
+
}
292
+
293
+
async fn fetch_master_key(&self) -> Result<Option<MasterKey>, PgStoreError> {
294
+
sqlx::query_scalar!("SELECT value FROM signal_kv WHERE key = 'master_key' LIMIT 1")
295
+
.fetch_optional(&self.db)
296
+
.await?
297
+
.map(|value| MasterKey::from_slice(&value))
298
+
.transpose()
299
+
.map_err(|_| PgStoreError::InvalidFormat)
300
+
}
301
+
302
+
async fn store_master_key(&self, master_key: Option<&MasterKey>) -> Result<(), PgStoreError> {
303
+
match master_key {
304
+
Some(k) => {
305
+
let value = k.inner.to_vec();
306
+
sqlx::query!(
307
+
"INSERT INTO signal_kv (key, value) VALUES ('master_key', $1)
308
+
ON CONFLICT (key) DO UPDATE SET value = $1",
309
+
&value,
310
+
)
311
+
.execute(&self.db)
312
+
.await?;
313
+
}
314
+
None => {
315
+
sqlx::query!("DELETE FROM signal_kv WHERE key = 'master_key'")
316
+
.execute(&self.db)
317
+
.await?;
318
+
}
319
+
}
320
+
Ok(())
321
+
}
322
+
}
323
+
324
+
impl ProtocolStore for PgProtocolStore {}
325
+
326
+
#[async_trait(?Send)]
327
+
impl SessionStore for PgProtocolStore {
328
+
async fn load_session(
329
+
&self,
330
+
address: &ProtocolAddress,
331
+
) -> Result<Option<SessionRecord>, SignalProtocolError> {
332
+
let device_id: i32 = u32_to_i32(u32::from(address.device_id()))?;
333
+
let identity = self.identity.as_str();
334
+
let addr = address.name();
335
+
sqlx::query_scalar!(
336
+
"SELECT record FROM signal_sessions
337
+
WHERE address = $1 AND device_id = $2 AND identity = $3",
338
+
addr,
339
+
device_id,
340
+
identity,
341
+
)
342
+
.fetch_optional(&self.store.db)
343
+
.await
344
+
.into_protocol_error()?
345
+
.map(|record| SessionRecord::deserialize(&record))
346
+
.transpose()
347
+
}
348
+
349
+
async fn store_session(
350
+
&mut self,
351
+
address: &ProtocolAddress,
352
+
record: &SessionRecord,
353
+
) -> Result<(), SignalProtocolError> {
354
+
let device_id: i32 = u32_to_i32(u32::from(address.device_id()))?;
355
+
let identity = self.identity.as_str();
356
+
let addr = address.name();
357
+
let record = record.serialize()?;
358
+
sqlx::query!(
359
+
"INSERT INTO signal_sessions (address, device_id, identity, record)
360
+
VALUES ($1, $2, $3, $4)
361
+
ON CONFLICT (address, device_id, identity) DO UPDATE SET record = $4",
362
+
addr,
363
+
device_id,
364
+
identity,
365
+
&record,
366
+
)
367
+
.execute(&self.store.db)
368
+
.await
369
+
.into_protocol_error()?;
370
+
Ok(())
371
+
}
372
+
}
373
+
374
+
#[async_trait(?Send)]
375
+
impl SessionStoreExt for PgProtocolStore {
376
+
async fn get_sub_device_sessions(
377
+
&self,
378
+
name: &ServiceId,
379
+
) -> Result<Vec<DeviceId>, SignalProtocolError> {
380
+
let address = name.raw_uuid().to_string();
381
+
let default_device: i32 = u32_to_i32(u32::from(*DEFAULT_DEVICE_ID))?;
382
+
let identity = self.identity.as_str();
383
+
sqlx::query_scalar!(
384
+
"SELECT device_id FROM signal_sessions
385
+
WHERE address = $1 AND device_id != $2 AND identity = $3",
386
+
&address,
387
+
default_device,
388
+
identity,
389
+
)
390
+
.fetch_all(&self.store.db)
391
+
.await
392
+
.into_protocol_error()?
393
+
.into_iter()
394
+
.map(|id| {
395
+
let v = i32_to_u32(id)?;
396
+
let byte = u8::try_from(v).map_err(|_| {
397
+
SignalProtocolError::InvalidState("device id", format!("{id} exceeds u8::MAX"))
398
+
})?;
399
+
DeviceId::new(byte).map_err(|_| {
400
+
SignalProtocolError::InvalidState("device id", format!("invalid device id {id}"))
401
+
})
402
+
})
403
+
.collect()
404
+
}
405
+
406
+
async fn delete_session(&self, address: &ProtocolAddress) -> Result<(), SignalProtocolError> {
407
+
let device_id: i32 = u32_to_i32(u32::from(address.device_id()))?;
408
+
let identity = self.identity.as_str();
409
+
let addr = address.name();
410
+
sqlx::query!(
411
+
"DELETE FROM signal_sessions WHERE address = $1 AND device_id = $2 AND identity = $3",
412
+
addr,
413
+
device_id,
414
+
identity,
415
+
)
416
+
.execute(&self.store.db)
417
+
.await
418
+
.into_protocol_error()?;
419
+
Ok(())
420
+
}
421
+
422
+
async fn delete_all_sessions(&self, name: &ServiceId) -> Result<usize, SignalProtocolError> {
423
+
let address = name.raw_uuid().to_string();
424
+
let identity = self.identity.as_str();
425
+
let res = sqlx::query!(
426
+
"DELETE FROM signal_sessions WHERE address = $1 AND identity = $2",
427
+
&address,
428
+
identity,
429
+
)
430
+
.execute(&self.store.db)
431
+
.await
432
+
.into_protocol_error()?;
433
+
Ok(usize::try_from(res.rows_affected()).unwrap_or(usize::MAX))
434
+
}
435
+
}
436
+
437
+
#[async_trait(?Send)]
438
+
impl PreKeyStore for PgProtocolStore {
439
+
async fn get_pre_key(&self, prekey_id: PreKeyId) -> Result<PreKeyRecord, SignalProtocolError> {
440
+
let id: i32 = u32_to_i32(u32::from(prekey_id))?;
441
+
let identity = self.identity.as_str();
442
+
let record = sqlx::query_scalar!(
443
+
"SELECT record FROM signal_pre_keys WHERE id = $1 AND identity = $2",
444
+
id,
445
+
identity,
446
+
)
447
+
.fetch_one(&self.store.db)
448
+
.await
449
+
.into_protocol_error()?;
450
+
PreKeyRecord::deserialize(&record)
451
+
}
452
+
453
+
async fn save_pre_key(
454
+
&mut self,
455
+
prekey_id: PreKeyId,
456
+
record: &PreKeyRecord,
457
+
) -> Result<(), SignalProtocolError> {
458
+
let id: i32 = u32_to_i32(u32::from(prekey_id))?;
459
+
let identity = self.identity.as_str();
460
+
let record = record.serialize()?;
461
+
sqlx::query!(
462
+
"INSERT INTO signal_pre_keys (id, identity, record)
463
+
VALUES ($1, $2, $3)
464
+
ON CONFLICT (id, identity) DO UPDATE SET record = $3",
465
+
id,
466
+
identity,
467
+
&record,
468
+
)
469
+
.execute(&self.store.db)
470
+
.await
471
+
.into_protocol_error()?;
472
+
Ok(())
473
+
}
474
+
475
+
async fn remove_pre_key(&mut self, prekey_id: PreKeyId) -> Result<(), SignalProtocolError> {
476
+
let id: i32 = u32_to_i32(u32::from(prekey_id))?;
477
+
let identity = self.identity.as_str();
478
+
sqlx::query!(
479
+
"DELETE FROM signal_pre_keys WHERE id = $1 AND identity = $2",
480
+
id,
481
+
identity,
482
+
)
483
+
.execute(&self.store.db)
484
+
.await
485
+
.into_protocol_error()?;
486
+
Ok(())
487
+
}
488
+
}
489
+
490
+
#[async_trait(?Send)]
491
+
impl PreKeysStore for PgProtocolStore {
492
+
async fn next_pre_key_id(&self) -> Result<u32, SignalProtocolError> {
493
+
let identity = self.identity.as_str();
494
+
let max_id = sqlx::query_scalar!(
495
+
"SELECT MAX(id) FROM signal_pre_keys WHERE identity = $1",
496
+
identity,
497
+
)
498
+
.fetch_one(&self.store.db)
499
+
.await
500
+
.into_protocol_error()?;
501
+
next_id_from_max(max_id)
502
+
}
503
+
504
+
async fn next_signed_pre_key_id(&self) -> Result<u32, SignalProtocolError> {
505
+
let identity = self.identity.as_str();
506
+
let max_id = sqlx::query_scalar!(
507
+
"SELECT MAX(id) FROM signal_signed_pre_keys WHERE identity = $1",
508
+
identity,
509
+
)
510
+
.fetch_one(&self.store.db)
511
+
.await
512
+
.into_protocol_error()?;
513
+
next_id_from_max(max_id)
514
+
}
515
+
516
+
async fn next_pq_pre_key_id(&self) -> Result<u32, SignalProtocolError> {
517
+
let identity = self.identity.as_str();
518
+
let max_id = sqlx::query_scalar!(
519
+
"SELECT MAX(id) FROM signal_kyber_pre_keys WHERE identity = $1",
520
+
identity,
521
+
)
522
+
.fetch_one(&self.store.db)
523
+
.await
524
+
.into_protocol_error()?;
525
+
next_id_from_max(max_id)
526
+
}
527
+
528
+
async fn signed_pre_keys_count(&self) -> Result<usize, SignalProtocolError> {
529
+
let identity = self.identity.as_str();
530
+
let count = sqlx::query_scalar!(
531
+
"SELECT COUNT(*) AS \"count!\" FROM signal_signed_pre_keys WHERE identity = $1",
532
+
identity,
533
+
)
534
+
.fetch_one(&self.store.db)
535
+
.await
536
+
.into_protocol_error()?;
537
+
Ok(usize::try_from(count).unwrap_or(usize::MAX))
538
+
}
539
+
540
+
async fn kyber_pre_keys_count(&self, last_resort: bool) -> Result<usize, SignalProtocolError> {
541
+
let identity = self.identity.as_str();
542
+
let count = sqlx::query_scalar!(
543
+
"SELECT COUNT(*) AS \"count!\" FROM signal_kyber_pre_keys
544
+
WHERE identity = $1 AND is_last_resort = $2",
545
+
identity,
546
+
last_resort,
547
+
)
548
+
.fetch_one(&self.store.db)
549
+
.await
550
+
.into_protocol_error()?;
551
+
Ok(usize::try_from(count).unwrap_or(usize::MAX))
552
+
}
553
+
554
+
async fn signed_prekey_id(&self) -> Result<Option<SignedPreKeyId>, SignalProtocolError> {
555
+
let identity = self.identity.as_str();
556
+
let max_id = sqlx::query_scalar!(
557
+
"SELECT MAX(id) FROM signal_signed_pre_keys WHERE identity = $1",
558
+
identity,
559
+
)
560
+
.fetch_one(&self.store.db)
561
+
.await
562
+
.into_protocol_error()?;
563
+
max_id
564
+
.map(|id| i32_to_u32(id).map(SignedPreKeyId::from))
565
+
.transpose()
566
+
}
567
+
568
+
async fn last_resort_kyber_prekey_id(
569
+
&self,
570
+
) -> Result<Option<KyberPreKeyId>, SignalProtocolError> {
571
+
let identity = self.identity.as_str();
572
+
let max_id = sqlx::query_scalar!(
573
+
"SELECT MAX(id) FROM signal_kyber_pre_keys
574
+
WHERE identity = $1 AND is_last_resort = TRUE",
575
+
identity,
576
+
)
577
+
.fetch_one(&self.store.db)
578
+
.await
579
+
.into_protocol_error()?;
580
+
max_id
581
+
.map(|id| i32_to_u32(id).map(KyberPreKeyId::from))
582
+
.transpose()
583
+
}
584
+
}
585
+
586
+
#[async_trait(?Send)]
587
+
impl SignedPreKeyStore for PgProtocolStore {
588
+
async fn get_signed_pre_key(
589
+
&self,
590
+
signed_prekey_id: SignedPreKeyId,
591
+
) -> Result<SignedPreKeyRecord, SignalProtocolError> {
592
+
let id: i32 = u32_to_i32(u32::from(signed_prekey_id))?;
593
+
let identity = self.identity.as_str();
594
+
let bytes = sqlx::query_scalar!(
595
+
"SELECT record FROM signal_signed_pre_keys WHERE id = $1 AND identity = $2",
596
+
id,
597
+
identity,
598
+
)
599
+
.fetch_one(&self.store.db)
600
+
.await
601
+
.into_protocol_error()?;
602
+
SignedPreKeyRecord::deserialize(&bytes)
603
+
}
604
+
605
+
async fn save_signed_pre_key(
606
+
&mut self,
607
+
signed_prekey_id: SignedPreKeyId,
608
+
record: &SignedPreKeyRecord,
609
+
) -> Result<(), SignalProtocolError> {
610
+
let id: i32 = u32_to_i32(u32::from(signed_prekey_id))?;
611
+
let identity = self.identity.as_str();
612
+
let bytes = record.serialize()?;
613
+
sqlx::query!(
614
+
"INSERT INTO signal_signed_pre_keys (id, identity, record)
615
+
VALUES ($1, $2, $3)
616
+
ON CONFLICT (id, identity) DO UPDATE SET record = $3",
617
+
id,
618
+
identity,
619
+
&bytes,
620
+
)
621
+
.execute(&self.store.db)
622
+
.await
623
+
.into_protocol_error()?;
624
+
Ok(())
625
+
}
626
+
}
627
+
628
+
#[async_trait(?Send)]
629
+
impl KyberPreKeyStore for PgProtocolStore {
630
+
async fn get_kyber_pre_key(
631
+
&self,
632
+
kyber_prekey_id: KyberPreKeyId,
633
+
) -> Result<KyberPreKeyRecord, SignalProtocolError> {
634
+
let id: i32 = u32_to_i32(u32::from(kyber_prekey_id))?;
635
+
let identity = self.identity.as_str();
636
+
let bytes = sqlx::query_scalar!(
637
+
"SELECT record FROM signal_kyber_pre_keys WHERE id = $1 AND identity = $2",
638
+
id,
639
+
identity,
640
+
)
641
+
.fetch_one(&self.store.db)
642
+
.await
643
+
.into_protocol_error()?;
644
+
KyberPreKeyRecord::deserialize(&bytes)
645
+
}
646
+
647
+
async fn save_kyber_pre_key(
648
+
&mut self,
649
+
kyber_prekey_id: KyberPreKeyId,
650
+
record: &KyberPreKeyRecord,
651
+
) -> Result<(), SignalProtocolError> {
652
+
let id: i32 = u32_to_i32(u32::from(kyber_prekey_id))?;
653
+
let identity = self.identity.as_str();
654
+
let record = record.serialize()?;
655
+
sqlx::query!(
656
+
"INSERT INTO signal_kyber_pre_keys (id, identity, record, is_last_resort)
657
+
VALUES ($1, $2, $3, FALSE)
658
+
ON CONFLICT (id, identity) DO UPDATE SET record = $3, is_last_resort = FALSE",
659
+
id,
660
+
identity,
661
+
&record,
662
+
)
663
+
.execute(&self.store.db)
664
+
.await
665
+
.into_protocol_error()?;
666
+
Ok(())
667
+
}
668
+
669
+
async fn mark_kyber_pre_key_used(
670
+
&mut self,
671
+
kyber_prekey_id: KyberPreKeyId,
672
+
ec_prekey_id: SignedPreKeyId,
673
+
base_key: &PublicKey,
674
+
) -> Result<(), SignalProtocolError> {
675
+
let mut tx = self.store.db.begin().await.into_protocol_error()?;
676
+
let kyber_id: i32 = u32_to_i32(u32::from(kyber_prekey_id))?;
677
+
let identity = self.identity.as_str();
678
+
679
+
let is_last_resort = sqlx::query_scalar!(
680
+
"SELECT is_last_resort FROM signal_kyber_pre_keys WHERE id = $1 AND identity = $2",
681
+
kyber_id,
682
+
identity,
683
+
)
684
+
.fetch_one(&mut *tx)
685
+
.await
686
+
.into_protocol_error()?;
687
+
688
+
if is_last_resort {
689
+
let ec_id: i32 = u32_to_i32(u32::from(ec_prekey_id))?;
690
+
let base_key_bytes = base_key.serialize().to_vec();
691
+
692
+
let result = sqlx::query!(
693
+
"INSERT INTO signal_base_keys_seen
694
+
(kyber_pre_key_id, signed_pre_key_id, identity, base_key)
695
+
VALUES ($1, $2, $3, $4)",
696
+
kyber_id,
697
+
ec_id,
698
+
identity,
699
+
&base_key_bytes,
700
+
)
701
+
.execute(&mut *tx)
702
+
.await;
703
+
704
+
match result {
705
+
Err(sqlx::Error::Database(ref e)) if e.is_unique_violation() => {
706
+
return Err(SignalProtocolError::InvalidMessage(
707
+
CiphertextMessageType::PreKey,
708
+
"reused base key",
709
+
));
710
+
}
711
+
other => {
712
+
other.into_protocol_error()?;
713
+
}
714
+
}
715
+
} else {
716
+
sqlx::query!(
717
+
"DELETE FROM signal_kyber_pre_keys
718
+
WHERE id = $1 AND identity = $2 AND is_last_resort = FALSE",
719
+
kyber_id,
720
+
identity,
721
+
)
722
+
.execute(&mut *tx)
723
+
.await
724
+
.into_protocol_error()?;
725
+
}
726
+
727
+
tx.commit().await.into_protocol_error()?;
728
+
Ok(())
729
+
}
730
+
}
731
+
732
+
#[async_trait(?Send)]
733
+
impl KyberPreKeyStoreExt for PgProtocolStore {
734
+
async fn store_last_resort_kyber_pre_key(
735
+
&mut self,
736
+
kyber_prekey_id: KyberPreKeyId,
737
+
record: &KyberPreKeyRecord,
738
+
) -> Result<(), SignalProtocolError> {
739
+
let id: i32 = u32_to_i32(u32::from(kyber_prekey_id))?;
740
+
let identity = self.identity.as_str();
741
+
let record = record.serialize()?;
742
+
sqlx::query!(
743
+
"INSERT INTO signal_kyber_pre_keys (id, identity, record, is_last_resort)
744
+
VALUES ($1, $2, $3, TRUE)
745
+
ON CONFLICT (id, identity) DO UPDATE SET is_last_resort = TRUE, record = $3",
746
+
id,
747
+
identity,
748
+
&record,
749
+
)
750
+
.execute(&self.store.db)
751
+
.await
752
+
.into_protocol_error()?;
753
+
Ok(())
754
+
}
755
+
756
+
async fn load_last_resort_kyber_pre_keys(
757
+
&self,
758
+
) -> Result<Vec<KyberPreKeyRecord>, SignalProtocolError> {
759
+
let identity = self.identity.as_str();
760
+
sqlx::query_scalar!(
761
+
"SELECT record FROM signal_kyber_pre_keys
762
+
WHERE identity = $1 AND is_last_resort = TRUE",
763
+
identity,
764
+
)
765
+
.fetch_all(&self.store.db)
766
+
.await
767
+
.into_protocol_error()?
768
+
.into_iter()
769
+
.map(|record| KyberPreKeyRecord::deserialize(&record))
770
+
.collect()
771
+
}
772
+
773
+
async fn remove_kyber_pre_key(
774
+
&mut self,
775
+
kyber_prekey_id: KyberPreKeyId,
776
+
) -> Result<(), SignalProtocolError> {
777
+
let id: i32 = u32_to_i32(u32::from(kyber_prekey_id))?;
778
+
let identity = self.identity.as_str();
779
+
sqlx::query!(
780
+
"DELETE FROM signal_kyber_pre_keys WHERE id = $1 AND identity = $2",
781
+
id,
782
+
identity,
783
+
)
784
+
.execute(&self.store.db)
785
+
.await
786
+
.into_protocol_error()?;
787
+
Ok(())
788
+
}
789
+
790
+
async fn mark_all_one_time_kyber_pre_keys_stale_if_necessary(
791
+
&mut self,
792
+
stale_time: chrono::DateTime<chrono::Utc>,
793
+
) -> Result<(), SignalProtocolError> {
794
+
let identity = self.identity.as_str();
795
+
sqlx::query!(
796
+
"UPDATE signal_kyber_pre_keys
797
+
SET stale_at = $1
798
+
WHERE identity = $2 AND is_last_resort = FALSE AND stale_at IS NULL",
799
+
stale_time,
800
+
identity,
801
+
)
802
+
.execute(&self.store.db)
803
+
.await
804
+
.into_protocol_error()?;
805
+
Ok(())
806
+
}
807
+
808
+
async fn delete_all_stale_one_time_kyber_pre_keys(
809
+
&mut self,
810
+
threshold: chrono::DateTime<chrono::Utc>,
811
+
min_count: usize,
812
+
) -> Result<(), SignalProtocolError> {
813
+
let identity = self.identity.as_str();
814
+
let min_count = i64::try_from(min_count).unwrap_or(i64::MAX);
815
+
sqlx::query!(
816
+
"WITH total AS (
817
+
SELECT COUNT(*) AS cnt FROM signal_kyber_pre_keys
818
+
WHERE identity = $1 AND is_last_resort = FALSE
819
+
)
820
+
DELETE FROM signal_kyber_pre_keys
821
+
WHERE identity = $1 AND is_last_resort = FALSE
822
+
AND stale_at IS NOT NULL AND stale_at < $2
823
+
AND (SELECT cnt FROM total) > $3",
824
+
identity,
825
+
threshold,
826
+
min_count,
827
+
)
828
+
.execute(&self.store.db)
829
+
.await
830
+
.into_protocol_error()?;
831
+
Ok(())
832
+
}
833
+
}
834
+
835
+
#[async_trait(?Send)]
836
+
impl IdentityKeyStore for PgProtocolStore {
837
+
async fn get_identity_key_pair(&self) -> Result<IdentityKeyPair, SignalProtocolError> {
838
+
let key = self.identity.identity_key_pair_key();
839
+
let bytes = sqlx::query_scalar!("SELECT value FROM signal_kv WHERE key = $1", key,)
840
+
.fetch_one(&self.store.db)
841
+
.await
842
+
.into_protocol_error()?;
843
+
IdentityKeyPair::try_from(&*bytes)
844
+
}
845
+
846
+
async fn get_local_registration_id(&self) -> Result<u32, SignalProtocolError> {
847
+
let data = self
848
+
.store
849
+
.load_registration_data()
850
+
.await
851
+
.into_protocol_error()?
852
+
.ok_or_else(|| {
853
+
SignalProtocolError::InvalidState(
854
+
"failed to load registration ID",
855
+
"no registration data".into(),
856
+
)
857
+
})?;
858
+
Ok(data.registration_id)
859
+
}
860
+
861
+
async fn save_identity(
862
+
&mut self,
863
+
address: &ProtocolAddress,
864
+
identity_key: &IdentityKey,
865
+
) -> Result<IdentityChange, SignalProtocolError> {
866
+
let existing = self.get_identity(address).await?;
867
+
868
+
let addr = address.name();
869
+
let identity = self.identity.as_str();
870
+
let bytes = identity_key.serialize().to_vec();
871
+
872
+
sqlx::query!(
873
+
"INSERT INTO signal_identities (address, identity, record)
874
+
VALUES ($1, $2, $3)
875
+
ON CONFLICT (address, identity) DO UPDATE SET record = $3",
876
+
addr,
877
+
identity,
878
+
&bytes,
879
+
)
880
+
.execute(&self.store.db)
881
+
.await
882
+
.into_protocol_error()?;
883
+
884
+
Ok(match existing {
885
+
Some(k) if k == *identity_key => IdentityChange::NewOrUnchanged,
886
+
Some(_) => IdentityChange::ReplacedExisting,
887
+
None => IdentityChange::NewOrUnchanged,
888
+
})
889
+
}
890
+
891
+
async fn is_trusted_identity(
892
+
&self,
893
+
address: &ProtocolAddress,
894
+
identity_key: &IdentityKey,
895
+
_direction: Direction,
896
+
) -> Result<bool, SignalProtocolError> {
897
+
match self.get_identity(address).await? {
898
+
Some(trusted_key) if identity_key == &trusted_key => Ok(true),
899
+
Some(_) => {
900
+
warn!(%address, "trusting changed identity");
901
+
Ok(true)
902
+
}
903
+
None => {
904
+
warn!(%address, "trusting new identity");
905
+
Ok(true)
906
+
}
907
+
}
908
+
}
909
+
910
+
async fn get_identity(
911
+
&self,
912
+
address: &ProtocolAddress,
913
+
) -> Result<Option<IdentityKey>, SignalProtocolError> {
914
+
let addr = address.name();
915
+
let identity = self.identity.as_str();
916
+
sqlx::query_scalar!(
917
+
"SELECT record FROM signal_identities WHERE address = $1 AND identity = $2",
918
+
addr,
919
+
identity,
920
+
)
921
+
.fetch_optional(&self.store.db)
922
+
.await
923
+
.into_protocol_error()?
924
+
.map(|bytes| IdentityKey::decode(&bytes))
925
+
.transpose()
926
+
}
927
+
}
928
+
929
+
#[async_trait(?Send)]
930
+
impl SenderKeyStore for PgProtocolStore {
931
+
async fn store_sender_key(
932
+
&mut self,
933
+
sender: &ProtocolAddress,
934
+
distribution_id: Uuid,
935
+
record: &SenderKeyRecord,
936
+
) -> Result<(), SignalProtocolError> {
937
+
let device_id: i32 = u32_to_i32(u32::from(sender.device_id()))?;
938
+
let identity = self.identity.as_str();
939
+
let addr = sender.name();
940
+
let record = record.serialize()?;
941
+
sqlx::query!(
942
+
"INSERT INTO signal_sender_keys
943
+
(address, device_id, identity, distribution_id, record)
944
+
VALUES ($1, $2, $3, $4, $5)
945
+
ON CONFLICT (address, device_id, identity, distribution_id) DO UPDATE SET record = $5",
946
+
addr,
947
+
device_id,
948
+
identity,
949
+
distribution_id,
950
+
&record,
951
+
)
952
+
.execute(&self.store.db)
953
+
.await
954
+
.into_protocol_error()?;
955
+
Ok(())
956
+
}
957
+
958
+
async fn load_sender_key(
959
+
&mut self,
960
+
sender: &ProtocolAddress,
961
+
distribution_id: Uuid,
962
+
) -> Result<Option<SenderKeyRecord>, SignalProtocolError> {
963
+
let device_id: i32 = u32_to_i32(u32::from(sender.device_id()))?;
964
+
let identity = self.identity.as_str();
965
+
let addr = sender.name();
966
+
sqlx::query_scalar!(
967
+
"SELECT record FROM signal_sender_keys
968
+
WHERE address = $1 AND device_id = $2 AND identity = $3 AND distribution_id = $4",
969
+
addr,
970
+
device_id,
971
+
identity,
972
+
distribution_id,
973
+
)
974
+
.fetch_optional(&self.store.db)
975
+
.await
976
+
.into_protocol_error()?
977
+
.map(|record| SenderKeyRecord::deserialize(&record))
978
+
.transpose()
979
+
}
980
+
}
981
+
982
+
type EmptyIter<T> = std::iter::Empty<Result<T, PgStoreError>>;
983
+
984
+
impl ContentsStore for PgSignalStore {
985
+
type ContentsStoreError = PgStoreError;
986
+
type ContactsIter = EmptyIter<Contact>;
987
+
type GroupsIter = EmptyIter<(GroupMasterKeyBytes, Group)>;
988
+
type MessagesIter = EmptyIter<Content>;
989
+
type StickerPacksIter = EmptyIter<StickerPack>;
990
+
991
+
async fn clear_profiles(&mut self) -> Result<(), PgStoreError> {
992
+
sqlx::query!("DELETE FROM signal_profile_keys")
993
+
.execute(&self.db)
994
+
.await?;
995
+
Ok(())
996
+
}
997
+
998
+
async fn clear_contents(&mut self) -> Result<(), PgStoreError> {
999
+
Ok(())
1000
+
}
1001
+
1002
+
async fn clear_messages(&mut self) -> Result<(), PgStoreError> {
1003
+
Ok(())
1004
+
}
1005
+
1006
+
async fn clear_thread(&mut self, _thread: &Thread) -> Result<(), PgStoreError> {
1007
+
Ok(())
1008
+
}
1009
+
1010
+
async fn save_message(&self, _thread: &Thread, _message: Content) -> Result<(), PgStoreError> {
1011
+
Ok(())
1012
+
}
1013
+
1014
+
async fn delete_message(
1015
+
&mut self,
1016
+
_thread: &Thread,
1017
+
_timestamp: u64,
1018
+
) -> Result<bool, PgStoreError> {
1019
+
Ok(false)
1020
+
}
1021
+
1022
+
async fn message(
1023
+
&self,
1024
+
_thread: &Thread,
1025
+
_timestamp: u64,
1026
+
) -> Result<Option<Content>, PgStoreError> {
1027
+
Ok(None)
1028
+
}
1029
+
1030
+
async fn messages(
1031
+
&self,
1032
+
_thread: &Thread,
1033
+
_range: impl RangeBounds<u64>,
1034
+
) -> Result<Self::MessagesIter, PgStoreError> {
1035
+
Ok(std::iter::empty())
1036
+
}
1037
+
1038
+
async fn clear_contacts(&mut self) -> Result<(), PgStoreError> {
1039
+
Ok(())
1040
+
}
1041
+
1042
+
async fn save_contact(&mut self, _contact: &Contact) -> Result<(), PgStoreError> {
1043
+
Ok(())
1044
+
}
1045
+
1046
+
async fn contacts(&self) -> Result<Self::ContactsIter, PgStoreError> {
1047
+
Ok(std::iter::empty())
1048
+
}
1049
+
1050
+
async fn contact_by_id(&self, _id: &ServiceId) -> Result<Option<Contact>, PgStoreError> {
1051
+
Ok(None)
1052
+
}
1053
+
1054
+
async fn clear_groups(&mut self) -> Result<(), PgStoreError> {
1055
+
Ok(())
1056
+
}
1057
+
1058
+
async fn save_group(
1059
+
&self,
1060
+
_master_key: GroupMasterKeyBytes,
1061
+
_group: impl Into<Group>,
1062
+
) -> Result<(), PgStoreError> {
1063
+
Ok(())
1064
+
}
1065
+
1066
+
async fn groups(&self) -> Result<Self::GroupsIter, PgStoreError> {
1067
+
Ok(std::iter::empty())
1068
+
}
1069
+
1070
+
async fn group(&self, _master_key: GroupMasterKeyBytes) -> Result<Option<Group>, PgStoreError> {
1071
+
Ok(None)
1072
+
}
1073
+
1074
+
async fn save_group_avatar(
1075
+
&self,
1076
+
_master_key: GroupMasterKeyBytes,
1077
+
_avatar: &AvatarBytes,
1078
+
) -> Result<(), PgStoreError> {
1079
+
Ok(())
1080
+
}
1081
+
1082
+
async fn group_avatar(
1083
+
&self,
1084
+
_master_key: GroupMasterKeyBytes,
1085
+
) -> Result<Option<AvatarBytes>, PgStoreError> {
1086
+
Ok(None)
1087
+
}
1088
+
1089
+
async fn upsert_profile_key(
1090
+
&mut self,
1091
+
uuid: &Uuid,
1092
+
key: ProfileKey,
1093
+
) -> Result<bool, PgStoreError> {
1094
+
let key_bytes = key.bytes.to_vec();
1095
+
let inserted = sqlx::query_scalar!(
1096
+
"INSERT INTO signal_profile_keys (uuid, key) VALUES ($1, $2)
1097
+
ON CONFLICT (uuid) DO UPDATE SET key = $2
1098
+
RETURNING (xmax = 0) AS \"inserted!\"",
1099
+
uuid,
1100
+
&key_bytes,
1101
+
)
1102
+
.fetch_one(&self.db)
1103
+
.await?;
1104
+
Ok(inserted)
1105
+
}
1106
+
1107
+
async fn profile_key(
1108
+
&self,
1109
+
service_id: &ServiceId,
1110
+
) -> Result<Option<ProfileKey>, PgStoreError> {
1111
+
let uuid: Uuid = service_id.raw_uuid();
1112
+
let row = sqlx::query!("SELECT key FROM signal_profile_keys WHERE uuid = $1", uuid,)
1113
+
.fetch_optional(&self.db)
1114
+
.await?;
1115
+
1116
+
Ok(match row {
1117
+
Some(r) => match <[u8; 32]>::try_from(r.key.as_slice()) {
1118
+
Ok(arr) => Some(ProfileKey { bytes: arr }),
1119
+
Err(_) => {
1120
+
warn!(%uuid, len = r.key.len(), "corrupted profile key (expected 32 bytes)");
1121
+
None
1122
+
}
1123
+
},
1124
+
None => None,
1125
+
})
1126
+
}
1127
+
1128
+
async fn save_profile(
1129
+
&mut self,
1130
+
_uuid: Uuid,
1131
+
_key: ProfileKey,
1132
+
_profile: Profile,
1133
+
) -> Result<(), PgStoreError> {
1134
+
Ok(())
1135
+
}
1136
+
1137
+
async fn profile(
1138
+
&self,
1139
+
_uuid: Uuid,
1140
+
_key: ProfileKey,
1141
+
) -> Result<Option<Profile>, PgStoreError> {
1142
+
Ok(None)
1143
+
}
1144
+
1145
+
async fn save_profile_avatar(
1146
+
&mut self,
1147
+
_uuid: Uuid,
1148
+
_key: ProfileKey,
1149
+
_profile: &AvatarBytes,
1150
+
) -> Result<(), PgStoreError> {
1151
+
Ok(())
1152
+
}
1153
+
1154
+
async fn profile_avatar(
1155
+
&self,
1156
+
_uuid: Uuid,
1157
+
_key: ProfileKey,
1158
+
) -> Result<Option<AvatarBytes>, PgStoreError> {
1159
+
Ok(None)
1160
+
}
1161
+
1162
+
async fn add_sticker_pack(&mut self, _pack: &StickerPack) -> Result<(), PgStoreError> {
1163
+
Ok(())
1164
+
}
1165
+
1166
+
async fn sticker_pack(&self, _id: &[u8]) -> Result<Option<StickerPack>, PgStoreError> {
1167
+
Ok(None)
1168
+
}
1169
+
1170
+
async fn remove_sticker_pack(&mut self, _id: &[u8]) -> Result<bool, PgStoreError> {
1171
+
Ok(false)
1172
+
}
1173
+
1174
+
async fn sticker_packs(&self) -> Result<Self::StickerPacksIter, PgStoreError> {
1175
+
Ok(std::iter::empty())
1176
+
}
1177
+
}
+64
migrations/20260321_signal_protocol_tables.sql
+64
migrations/20260321_signal_protocol_tables.sql
···
1
+
CREATE TABLE signal_kv (
2
+
key TEXT PRIMARY KEY,
3
+
value BYTEA NOT NULL
4
+
);
5
+
6
+
CREATE TABLE signal_sessions (
7
+
address TEXT NOT NULL,
8
+
device_id INTEGER NOT NULL CHECK (device_id BETWEEN 0 AND 127),
9
+
identity TEXT NOT NULL CHECK (identity IN ('aci', 'pni')),
10
+
record BYTEA NOT NULL,
11
+
PRIMARY KEY (address, device_id, identity)
12
+
);
13
+
14
+
CREATE TABLE signal_identities (
15
+
address TEXT NOT NULL,
16
+
identity TEXT NOT NULL CHECK (identity IN ('aci', 'pni')),
17
+
record BYTEA NOT NULL,
18
+
PRIMARY KEY (address, identity)
19
+
);
20
+
21
+
CREATE TABLE signal_pre_keys (
22
+
id INTEGER NOT NULL CHECK (id >= 0),
23
+
identity TEXT NOT NULL CHECK (identity IN ('aci', 'pni')),
24
+
record BYTEA NOT NULL,
25
+
PRIMARY KEY (id, identity)
26
+
);
27
+
28
+
CREATE TABLE signal_signed_pre_keys (
29
+
id INTEGER NOT NULL CHECK (id >= 0),
30
+
identity TEXT NOT NULL CHECK (identity IN ('aci', 'pni')),
31
+
record BYTEA NOT NULL,
32
+
PRIMARY KEY (id, identity)
33
+
);
34
+
35
+
CREATE TABLE signal_kyber_pre_keys (
36
+
id INTEGER NOT NULL CHECK (id >= 0),
37
+
identity TEXT NOT NULL CHECK (identity IN ('aci', 'pni')),
38
+
record BYTEA NOT NULL,
39
+
is_last_resort BOOLEAN NOT NULL DEFAULT FALSE,
40
+
stale_at TIMESTAMPTZ,
41
+
PRIMARY KEY (id, identity)
42
+
);
43
+
44
+
CREATE TABLE signal_sender_keys (
45
+
address TEXT NOT NULL,
46
+
device_id INTEGER NOT NULL CHECK (device_id BETWEEN 0 AND 127),
47
+
identity TEXT NOT NULL CHECK (identity IN ('aci', 'pni')),
48
+
distribution_id UUID NOT NULL,
49
+
record BYTEA NOT NULL,
50
+
PRIMARY KEY (address, device_id, identity, distribution_id)
51
+
);
52
+
53
+
CREATE TABLE signal_base_keys_seen (
54
+
kyber_pre_key_id INTEGER NOT NULL CHECK (kyber_pre_key_id >= 0),
55
+
signed_pre_key_id INTEGER NOT NULL CHECK (signed_pre_key_id >= 0),
56
+
identity TEXT NOT NULL CHECK (identity IN ('aci', 'pni')),
57
+
base_key BYTEA NOT NULL,
58
+
PRIMARY KEY (identity, kyber_pre_key_id, signed_pre_key_id, base_key)
59
+
);
60
+
61
+
CREATE TABLE signal_profile_keys (
62
+
uuid UUID PRIMARY KEY,
63
+
key BYTEA NOT NULL
64
+
);
History
1 round
0 comments
oyster.cafe
submitted
#0
1 commit
expand
collapse
feat(signal): add postgres-backed signal protocol store
expand 0 comments
pull request successfully merged