mirror of
https://github.com/chatmail/core.git
synced 2026-05-09 01:46:30 +03:00
build: update to rPGP 0.16.0 (#6719)
Co-authored-by: Heiko Schaefer <heiko@schaefer.name> Co-authored-by: link2xt <link2xt@testrun.org>
This commit is contained in:
committed by
GitHub
parent
42975b2ff3
commit
5c2af42cdd
180
Cargo.lock
generated
180
Cargo.lock
generated
@@ -439,10 +439,25 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||||||
checksum = "8c3c1a368f70d6cf7302d78f8f7093da241fb8e8807c05cc9e51a125895a6d5b"
|
checksum = "8c3c1a368f70d6cf7302d78f8f7093da241fb8e8807c05cc9e51a125895a6d5b"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "bitfield"
|
name = "bitfields"
|
||||||
version = "0.17.0"
|
version = "0.12.4"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "f798d2d157e547aa99aab0967df39edd0b70307312b6f8bd2848e6abe40896e0"
|
checksum = "a1d84268bbf9b487d31fe4b849edbefcd3911422d7a07de855a2da1f70ab3d1c"
|
||||||
|
dependencies = [
|
||||||
|
"bitfields-impl",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "bitfields-impl"
|
||||||
|
version = "0.9.4"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "07c93edde7bb4416c35c85048e34f78999dcb47d199bde3b1d79286156f3e2fb"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"syn 2.0.101",
|
||||||
|
"thiserror 2.0.12",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "bitflags"
|
name = "bitflags"
|
||||||
@@ -456,6 +471,18 @@ version = "2.8.0"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "8f68f53c83ab957f72c32642f3868eec03eb974d1fb82e453128456482613d36"
|
checksum = "8f68f53c83ab957f72c32642f3868eec03eb974d1fb82e453128456482613d36"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "bitvec"
|
||||||
|
version = "1.0.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "1bc2832c24239b0141d5674bb9174f9d68a8b5b3f2753311927c172ca46f7e9c"
|
||||||
|
dependencies = [
|
||||||
|
"funty",
|
||||||
|
"radium",
|
||||||
|
"tap",
|
||||||
|
"wyz",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "blake2"
|
name = "blake2"
|
||||||
version = "0.10.6"
|
version = "0.10.6"
|
||||||
@@ -623,16 +650,6 @@ dependencies = [
|
|||||||
"alloc-stdlib",
|
"alloc-stdlib",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "bstr"
|
|
||||||
version = "1.11.3"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "531a9155a481e2ee699d4f98f43c0ca4ff8ee1bfd55c31e9e98fb29d2b176fe0"
|
|
||||||
dependencies = [
|
|
||||||
"memchr",
|
|
||||||
"serde",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "buffer-redux"
|
name = "buffer-redux"
|
||||||
version = "1.0.2"
|
version = "1.0.2"
|
||||||
@@ -1141,7 +1158,7 @@ dependencies = [
|
|||||||
"crypto_secretbox",
|
"crypto_secretbox",
|
||||||
"curve25519-dalek",
|
"curve25519-dalek",
|
||||||
"salsa20",
|
"salsa20",
|
||||||
"serdect",
|
"serdect 0.2.0",
|
||||||
"subtle",
|
"subtle",
|
||||||
"zeroize",
|
"zeroize",
|
||||||
]
|
]
|
||||||
@@ -1200,6 +1217,23 @@ dependencies = [
|
|||||||
"syn 2.0.101",
|
"syn 2.0.101",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "cx448"
|
||||||
|
version = "0.1.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "b4c0cf476284b03eb6c10e78787b21c7abb7d7d43cb2f02532ba6b831ed892fa"
|
||||||
|
dependencies = [
|
||||||
|
"crypto-bigint",
|
||||||
|
"elliptic-curve",
|
||||||
|
"pkcs8",
|
||||||
|
"rand_core 0.6.4",
|
||||||
|
"serdect 0.3.0",
|
||||||
|
"sha3",
|
||||||
|
"signature",
|
||||||
|
"subtle",
|
||||||
|
"zeroize",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "darling"
|
name = "darling"
|
||||||
version = "0.20.10"
|
version = "0.20.10"
|
||||||
@@ -1526,7 +1560,16 @@ version = "1.0.0"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "4a9b99b9cbbe49445b21764dc0625032a89b145a2642e67603e1c936f5458d05"
|
checksum = "4a9b99b9cbbe49445b21764dc0625032a89b145a2642e67603e1c936f5458d05"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"derive_more-impl",
|
"derive_more-impl 1.0.0",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "derive_more"
|
||||||
|
version = "2.0.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "093242cf7570c207c83073cf82f79706fe7b8317e98620a47d5be7c3d8497678"
|
||||||
|
dependencies = [
|
||||||
|
"derive_more-impl 2.0.1",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@@ -1541,6 +1584,18 @@ dependencies = [
|
|||||||
"unicode-xid",
|
"unicode-xid",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "derive_more-impl"
|
||||||
|
version = "2.0.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "bda628edc44c4bb645fbe0f758797143e4e07926f7ebf4e9bdfbd3d2ce621df3"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"syn 2.0.101",
|
||||||
|
"unicode-xid",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "des"
|
name = "des"
|
||||||
version = "0.8.1"
|
version = "0.8.1"
|
||||||
@@ -1735,6 +1790,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||||||
checksum = "b5e6043086bf7973472e0c7dff2142ea0b680d30e18d9cc40f267efbf222bd47"
|
checksum = "b5e6043086bf7973472e0c7dff2142ea0b680d30e18d9cc40f267efbf222bd47"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"base16ct",
|
"base16ct",
|
||||||
|
"base64ct",
|
||||||
"crypto-bigint",
|
"crypto-bigint",
|
||||||
"digest",
|
"digest",
|
||||||
"ff",
|
"ff",
|
||||||
@@ -1745,7 +1801,10 @@ dependencies = [
|
|||||||
"pkcs8",
|
"pkcs8",
|
||||||
"rand_core 0.6.4",
|
"rand_core 0.6.4",
|
||||||
"sec1",
|
"sec1",
|
||||||
|
"serde_json",
|
||||||
|
"serdect 0.2.0",
|
||||||
"subtle",
|
"subtle",
|
||||||
|
"tap",
|
||||||
"zeroize",
|
"zeroize",
|
||||||
]
|
]
|
||||||
|
|
||||||
@@ -1930,6 +1989,7 @@ version = "0.13.0"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "ded41244b729663b1e574f1b4fb731469f69f79c17667b5d776b16cda0479449"
|
checksum = "ded41244b729663b1e574f1b4fb731469f69f79c17667b5d776b16cda0479449"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
|
"bitvec",
|
||||||
"rand_core 0.6.4",
|
"rand_core 0.6.4",
|
||||||
"subtle",
|
"subtle",
|
||||||
]
|
]
|
||||||
@@ -1965,6 +2025,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||||||
checksum = "7ced92e76e966ca2fd84c8f7aa01a4aea65b0eb6648d72f7c8f3e2764a67fece"
|
checksum = "7ced92e76e966ca2fd84c8f7aa01a4aea65b0eb6648d72f7c8f3e2764a67fece"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"crc32fast",
|
"crc32fast",
|
||||||
|
"libz-rs-sys",
|
||||||
"miniz_oxide",
|
"miniz_oxide",
|
||||||
]
|
]
|
||||||
|
|
||||||
@@ -2002,6 +2063,12 @@ dependencies = [
|
|||||||
name = "format-flowed"
|
name = "format-flowed"
|
||||||
version = "1.0.0"
|
version = "1.0.0"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "funty"
|
||||||
|
version = "2.0.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "e6d5a32815ae3f33302d95fdcb2ce17862f8c65363dcfd29360480ba1001fc9c"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "futures"
|
name = "futures"
|
||||||
version = "0.3.31"
|
version = "0.3.31"
|
||||||
@@ -2867,7 +2934,7 @@ dependencies = [
|
|||||||
"crypto_box",
|
"crypto_box",
|
||||||
"data-encoding",
|
"data-encoding",
|
||||||
"der",
|
"der",
|
||||||
"derive_more",
|
"derive_more 1.0.0",
|
||||||
"ed25519-dalek",
|
"ed25519-dalek",
|
||||||
"futures-buffered",
|
"futures-buffered",
|
||||||
"futures-util",
|
"futures-util",
|
||||||
@@ -2921,7 +2988,7 @@ checksum = "f91ac4aaab68153d726c4e6b39c30f9f9253743f0e25664e52f4caeb46f48d11"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"curve25519-dalek",
|
"curve25519-dalek",
|
||||||
"data-encoding",
|
"data-encoding",
|
||||||
"derive_more",
|
"derive_more 1.0.0",
|
||||||
"ed25519-dalek",
|
"ed25519-dalek",
|
||||||
"rand_core 0.6.4",
|
"rand_core 0.6.4",
|
||||||
"serde",
|
"serde",
|
||||||
@@ -2951,7 +3018,7 @@ dependencies = [
|
|||||||
"anyhow",
|
"anyhow",
|
||||||
"async-channel 2.3.1",
|
"async-channel 2.3.1",
|
||||||
"bytes",
|
"bytes",
|
||||||
"derive_more",
|
"derive_more 1.0.0",
|
||||||
"ed25519-dalek",
|
"ed25519-dalek",
|
||||||
"futures-concurrency",
|
"futures-concurrency",
|
||||||
"futures-lite",
|
"futures-lite",
|
||||||
@@ -3062,7 +3129,7 @@ dependencies = [
|
|||||||
"bytes",
|
"bytes",
|
||||||
"cfg_aliases",
|
"cfg_aliases",
|
||||||
"data-encoding",
|
"data-encoding",
|
||||||
"derive_more",
|
"derive_more 1.0.0",
|
||||||
"getrandom 0.3.3",
|
"getrandom 0.3.3",
|
||||||
"hickory-resolver",
|
"hickory-resolver",
|
||||||
"http 1.1.0",
|
"http 1.1.0",
|
||||||
@@ -3110,12 +3177,6 @@ dependencies = [
|
|||||||
"windows-sys 0.52.0",
|
"windows-sys 0.52.0",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "iter-read"
|
|
||||||
version = "1.1.0"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "071ed4cc1afd86650602c7b11aa2e1ce30762a1c27193201cb5cee9c6ebb1294"
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "itertools"
|
name = "itertools"
|
||||||
version = "0.10.5"
|
version = "0.10.5"
|
||||||
@@ -3216,6 +3277,15 @@ dependencies = [
|
|||||||
"vcpkg",
|
"vcpkg",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "libz-rs-sys"
|
||||||
|
version = "0.5.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "6489ca9bd760fe9642d7644e827b0c9add07df89857b0416ee15c1cc1a3b8c5a"
|
||||||
|
dependencies = [
|
||||||
|
"zlib-rs",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "linux-raw-sys"
|
name = "linux-raw-sys"
|
||||||
version = "0.4.14"
|
version = "0.4.14"
|
||||||
@@ -3416,7 +3486,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||||||
checksum = "7bb0e5d99e681ab3c938842b96fcb41bf8a7bb4bfdb11ccbd653a7e83e06c794"
|
checksum = "7bb0e5d99e681ab3c938842b96fcb41bf8a7bb4bfdb11ccbd653a7e83e06c794"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"cfg_aliases",
|
"cfg_aliases",
|
||||||
"derive_more",
|
"derive_more 1.0.0",
|
||||||
"futures-buffered",
|
"futures-buffered",
|
||||||
"futures-lite",
|
"futures-lite",
|
||||||
"futures-util",
|
"futures-util",
|
||||||
@@ -3564,7 +3634,7 @@ dependencies = [
|
|||||||
"atomic-waker",
|
"atomic-waker",
|
||||||
"bytes",
|
"bytes",
|
||||||
"cfg_aliases",
|
"cfg_aliases",
|
||||||
"derive_more",
|
"derive_more 1.0.0",
|
||||||
"iroh-quinn-udp",
|
"iroh-quinn-udp",
|
||||||
"js-sys",
|
"js-sys",
|
||||||
"libc",
|
"libc",
|
||||||
@@ -4059,21 +4129,22 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "pgp"
|
name = "pgp"
|
||||||
version = "0.15.0"
|
version = "0.16.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "30249ac8a98b356b473b04bc5358c75a260aa96a295d0743ce752fe7b173f235"
|
checksum = "f91d320242d9b686612b15526fe38711afdf856e112eaa4775ce25b0d9b12b11"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
|
"aead",
|
||||||
"aes",
|
"aes",
|
||||||
"aes-gcm",
|
"aes-gcm",
|
||||||
"aes-kw",
|
"aes-kw",
|
||||||
"argon2",
|
"argon2",
|
||||||
"base64",
|
"base64",
|
||||||
"bitfield",
|
"bitfields",
|
||||||
"block-padding",
|
"block-padding",
|
||||||
"blowfish",
|
"blowfish",
|
||||||
"bstr",
|
|
||||||
"buffer-redux",
|
"buffer-redux",
|
||||||
"byteorder",
|
"byteorder",
|
||||||
|
"bytes",
|
||||||
"camellia",
|
"camellia",
|
||||||
"cast5",
|
"cast5",
|
||||||
"cfb-mode",
|
"cfb-mode",
|
||||||
@@ -4082,8 +4153,9 @@ dependencies = [
|
|||||||
"const-oid",
|
"const-oid",
|
||||||
"crc24",
|
"crc24",
|
||||||
"curve25519-dalek",
|
"curve25519-dalek",
|
||||||
|
"cx448",
|
||||||
"derive_builder",
|
"derive_builder",
|
||||||
"derive_more",
|
"derive_more 2.0.1",
|
||||||
"des",
|
"des",
|
||||||
"digest",
|
"digest",
|
||||||
"dsa",
|
"dsa",
|
||||||
@@ -4096,7 +4168,6 @@ dependencies = [
|
|||||||
"hex",
|
"hex",
|
||||||
"hkdf",
|
"hkdf",
|
||||||
"idea",
|
"idea",
|
||||||
"iter-read",
|
|
||||||
"k256",
|
"k256",
|
||||||
"log",
|
"log",
|
||||||
"md-5",
|
"md-5",
|
||||||
@@ -4109,6 +4180,7 @@ dependencies = [
|
|||||||
"p384",
|
"p384",
|
||||||
"p521",
|
"p521",
|
||||||
"rand 0.8.5",
|
"rand 0.8.5",
|
||||||
|
"regex",
|
||||||
"ripemd",
|
"ripemd",
|
||||||
"rsa",
|
"rsa",
|
||||||
"sha1",
|
"sha1",
|
||||||
@@ -4117,7 +4189,7 @@ dependencies = [
|
|||||||
"sha3",
|
"sha3",
|
||||||
"signature",
|
"signature",
|
||||||
"smallvec",
|
"smallvec",
|
||||||
"thiserror 2.0.12",
|
"snafu",
|
||||||
"twofish",
|
"twofish",
|
||||||
"x25519-dalek",
|
"x25519-dalek",
|
||||||
"zeroize",
|
"zeroize",
|
||||||
@@ -4343,7 +4415,7 @@ checksum = "7d6db66007eac4a0ec8331d0d20c734bd64f6445d64bbaf0d0a27fea7a054e36"
|
|||||||
dependencies = [
|
dependencies = [
|
||||||
"base64",
|
"base64",
|
||||||
"bytes",
|
"bytes",
|
||||||
"derive_more",
|
"derive_more 1.0.0",
|
||||||
"futures-lite",
|
"futures-lite",
|
||||||
"futures-util",
|
"futures-util",
|
||||||
"hyper-util",
|
"hyper-util",
|
||||||
@@ -4640,6 +4712,12 @@ version = "5.2.0"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "74765f6d916ee2faa39bc8e68e4f3ed8949b48cccdac59983d287a7cb71ce9c5"
|
checksum = "74765f6d916ee2faa39bc8e68e4f3ed8949b48cccdac59983d287a7cb71ce9c5"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "radium"
|
||||||
|
version = "0.7.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "dc33ff2d4973d518d823d61aa239014831e521c75da58e3df4840d3f47749d09"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "radix_trie"
|
name = "radix_trie"
|
||||||
version = "0.2.1"
|
version = "0.2.1"
|
||||||
@@ -5198,6 +5276,7 @@ dependencies = [
|
|||||||
"der",
|
"der",
|
||||||
"generic-array",
|
"generic-array",
|
||||||
"pkcs8",
|
"pkcs8",
|
||||||
|
"serdect 0.2.0",
|
||||||
"subtle",
|
"subtle",
|
||||||
"zeroize",
|
"zeroize",
|
||||||
]
|
]
|
||||||
@@ -5339,6 +5418,16 @@ dependencies = [
|
|||||||
"serde",
|
"serde",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "serdect"
|
||||||
|
version = "0.3.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "f42f67da2385b51a5f9652db9c93d78aeaf7610bf5ec366080b6de810604af53"
|
||||||
|
dependencies = [
|
||||||
|
"base16ct",
|
||||||
|
"serde",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "sha-1"
|
name = "sha-1"
|
||||||
version = "0.10.1"
|
version = "0.10.1"
|
||||||
@@ -5786,6 +5875,12 @@ version = "0.2.0"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "7b2093cf4c8eb1e67749a6762251bc9cd836b6fc171623bd0a9d324d37af2417"
|
checksum = "7b2093cf4c8eb1e67749a6762251bc9cd836b6fc171623bd0a9d324d37af2417"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "tap"
|
||||||
|
version = "1.0.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "tempfile"
|
name = "tempfile"
|
||||||
version = "3.19.1"
|
version = "3.19.1"
|
||||||
@@ -7051,6 +7146,15 @@ dependencies = [
|
|||||||
"web-sys",
|
"web-sys",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "wyz"
|
||||||
|
version = "0.5.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "05f360fc0b24296329c78fda852a1e9ae82de9cf7b27dae4b7f62f118f77b9ed"
|
||||||
|
dependencies = [
|
||||||
|
"tap",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "x25519-dalek"
|
name = "x25519-dalek"
|
||||||
version = "2.0.1"
|
version = "2.0.1"
|
||||||
@@ -7288,6 +7392,12 @@ dependencies = [
|
|||||||
"syn 2.0.101",
|
"syn 2.0.101",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "zlib-rs"
|
||||||
|
version = "0.5.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "868b928d7949e09af2f6086dfc1e01936064cc7a819253bce650d4e2a2d63ba8"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "zune-core"
|
name = "zune-core"
|
||||||
version = "0.4.12"
|
version = "0.4.12"
|
||||||
|
|||||||
@@ -74,7 +74,7 @@ num-derive = "0.4"
|
|||||||
num-traits = { workspace = true }
|
num-traits = { workspace = true }
|
||||||
parking_lot = "0.12"
|
parking_lot = "0.12"
|
||||||
percent-encoding = "2.3"
|
percent-encoding = "2.3"
|
||||||
pgp = { version = "0.15.0", default-features = false }
|
pgp = { version = "0.16.0", default-features = false }
|
||||||
pin-project = "1"
|
pin-project = "1"
|
||||||
qrcodegen = "1.7.0"
|
qrcodegen = "1.7.0"
|
||||||
quick-xml = "0.37"
|
quick-xml = "0.37"
|
||||||
|
|||||||
@@ -22,6 +22,8 @@ ignore = [
|
|||||||
skip = [
|
skip = [
|
||||||
{ name = "async-channel", version = "1.9.0" },
|
{ name = "async-channel", version = "1.9.0" },
|
||||||
{ name = "bitflags", version = "1.3.2" },
|
{ name = "bitflags", version = "1.3.2" },
|
||||||
|
{ name = "derive_more-impl", version = "1.0.0" },
|
||||||
|
{ name = "derive_more", version = "1.0.0" },
|
||||||
{ name = "event-listener", version = "2.5.3" },
|
{ name = "event-listener", version = "2.5.3" },
|
||||||
{ name = "generator", version = "0.7.5" },
|
{ name = "generator", version = "0.7.5" },
|
||||||
{ name = "getrandom", version = "0.2.12" },
|
{ name = "getrandom", version = "0.2.12" },
|
||||||
@@ -38,6 +40,7 @@ skip = [
|
|||||||
{ name = "regex-automata", version = "0.1.10" },
|
{ name = "regex-automata", version = "0.1.10" },
|
||||||
{ name = "regex-syntax", version = "0.6.29" },
|
{ name = "regex-syntax", version = "0.6.29" },
|
||||||
{ name = "rustix", version = "0.38.44" },
|
{ name = "rustix", version = "0.38.44" },
|
||||||
|
{ name = "serdect", version = "0.2.0" },
|
||||||
{ name = "spin", version = "0.9.8" },
|
{ name = "spin", version = "0.9.8" },
|
||||||
{ name = "strum_macros", version = "0.26.2" },
|
{ name = "strum_macros", version = "0.26.2" },
|
||||||
{ name = "strum", version = "0.26.2" },
|
{ name = "strum", version = "0.26.2" },
|
||||||
|
|||||||
@@ -10,8 +10,8 @@ use std::time::Duration;
|
|||||||
|
|
||||||
use anyhow::{bail, ensure, Context as _, Result};
|
use anyhow::{bail, ensure, Context as _, Result};
|
||||||
use async_channel::{self as channel, Receiver, Sender};
|
use async_channel::{self as channel, Receiver, Sender};
|
||||||
|
use pgp::composed::SignedPublicKey;
|
||||||
use pgp::types::PublicKeyTrait;
|
use pgp::types::PublicKeyTrait;
|
||||||
use pgp::SignedPublicKey;
|
|
||||||
use ratelimit::Ratelimit;
|
use ratelimit::Ratelimit;
|
||||||
use tokio::sync::{Mutex, Notify, RwLock};
|
use tokio::sync::{Mutex, Notify, RwLock};
|
||||||
|
|
||||||
@@ -1074,7 +1074,7 @@ impl Context {
|
|||||||
res += &format!("db_size_bytes {db_size}\n");
|
res += &format!("db_size_bytes {db_size}\n");
|
||||||
|
|
||||||
let secret_key = &load_self_secret_key(self).await?.primary_key;
|
let secret_key = &load_self_secret_key(self).await?.primary_key;
|
||||||
let key_created = secret_key.created_at().timestamp();
|
let key_created = secret_key.public_key().created_at().timestamp();
|
||||||
res += &format!("key_created {key_created}\n");
|
res += &format!("key_created {key_created}\n");
|
||||||
|
|
||||||
// how many of the chats active in the last months are:
|
// how many of the chats active in the last months are:
|
||||||
|
|||||||
@@ -15,10 +15,10 @@ use crate::pgp;
|
|||||||
/// Tries to decrypt a message, but only if it is structured as an Autocrypt message.
|
/// Tries to decrypt a message, but only if it is structured as an Autocrypt message.
|
||||||
///
|
///
|
||||||
/// If successful and the message is encrypted, returns decrypted body.
|
/// If successful and the message is encrypted, returns decrypted body.
|
||||||
pub fn try_decrypt(
|
pub fn try_decrypt<'a>(
|
||||||
mail: &ParsedMail<'_>,
|
mail: &'a ParsedMail<'a>,
|
||||||
private_keyring: &[SignedSecretKey],
|
private_keyring: &'a [SignedSecretKey],
|
||||||
) -> Result<Option<::pgp::composed::Message>> {
|
) -> Result<Option<::pgp::composed::Message<'static>>> {
|
||||||
let Some(encrypted_data_part) = get_encrypted_mime(mail) else {
|
let Some(encrypted_data_part) = get_encrypted_mime(mail) else {
|
||||||
return Ok(None);
|
return Ok(None);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -143,7 +143,7 @@ impl EncryptHelper {
|
|||||||
let cursor = Cursor::new(&mut raw_message);
|
let cursor = Cursor::new(&mut raw_message);
|
||||||
mail_to_encrypt.clone().write_part(cursor).ok();
|
mail_to_encrypt.clone().write_part(cursor).ok();
|
||||||
|
|
||||||
let ctext = pgp::pk_encrypt(&raw_message, keyring, Some(sign_key), compress).await?;
|
let ctext = pgp::pk_encrypt(raw_message, keyring, Some(sign_key), compress).await?;
|
||||||
|
|
||||||
Ok(ctext)
|
Ok(ctext)
|
||||||
}
|
}
|
||||||
@@ -153,9 +153,8 @@ impl EncryptHelper {
|
|||||||
pub async fn sign(self, context: &Context, mail: &MimePart<'static>) -> Result<String> {
|
pub async fn sign(self, context: &Context, mail: &MimePart<'static>) -> Result<String> {
|
||||||
let sign_key = load_self_secret_key(context).await?;
|
let sign_key = load_self_secret_key(context).await?;
|
||||||
let mut buffer = Vec::new();
|
let mut buffer = Vec::new();
|
||||||
let cursor = Cursor::new(&mut buffer);
|
mail.clone().write_part(&mut buffer)?;
|
||||||
mail.clone().write_part(cursor).ok();
|
let signature = pgp::pk_calc_signature(buffer, &sign_key)?;
|
||||||
let signature = pgp::pk_calc_signature(&buffer, &sign_key)?;
|
|
||||||
Ok(signature)
|
Ok(signature)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,7 +4,6 @@ use std::ffi::OsStr;
|
|||||||
use std::path::{Path, PathBuf};
|
use std::path::{Path, PathBuf};
|
||||||
use std::pin::Pin;
|
use std::pin::Pin;
|
||||||
|
|
||||||
use ::pgp::types::PublicKeyTrait;
|
|
||||||
use anyhow::{bail, ensure, format_err, Context as _, Result};
|
use anyhow::{bail, ensure, format_err, Context as _, Result};
|
||||||
use futures::TryStreamExt;
|
use futures::TryStreamExt;
|
||||||
use futures_lite::FutureExt;
|
use futures_lite::FutureExt;
|
||||||
@@ -32,6 +31,7 @@ use crate::tools::{
|
|||||||
mod key_transfer;
|
mod key_transfer;
|
||||||
mod transfer;
|
mod transfer;
|
||||||
|
|
||||||
|
use ::pgp::types::KeyDetails;
|
||||||
pub use key_transfer::{continue_key_transfer, initiate_key_transfer};
|
pub use key_transfer::{continue_key_transfer, initiate_key_transfer};
|
||||||
pub use transfer::{get_backup, BackupProvider};
|
pub use transfer::{get_backup, BackupProvider};
|
||||||
|
|
||||||
@@ -173,7 +173,11 @@ async fn set_self_key(context: &Context, armored: &str) -> Result<()> {
|
|||||||
};
|
};
|
||||||
key::store_self_keypair(context, &keypair).await?;
|
key::store_self_keypair(context, &keypair).await?;
|
||||||
|
|
||||||
info!(context, "stored self key: {:?}", keypair.secret.key_id());
|
info!(
|
||||||
|
context,
|
||||||
|
"stored self key: {:?}",
|
||||||
|
keypair.secret.public_key().key_id()
|
||||||
|
);
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,6 @@
|
|||||||
//! # Key transfer via Autocrypt Setup Message.
|
//! # Key transfer via Autocrypt Setup Message.
|
||||||
|
use std::io::BufReader;
|
||||||
|
|
||||||
use rand::{thread_rng, Rng};
|
use rand::{thread_rng, Rng};
|
||||||
|
|
||||||
use anyhow::{bail, ensure, Result};
|
use anyhow::{bail, ensure, Result};
|
||||||
@@ -71,7 +73,7 @@ pub async fn continue_key_transfer(
|
|||||||
if let Some(filename) = msg.get_file(context) {
|
if let Some(filename) = msg.get_file(context) {
|
||||||
let file = open_file_std(context, filename)?;
|
let file = open_file_std(context, filename)?;
|
||||||
let sc = normalize_setup_code(setup_code);
|
let sc = normalize_setup_code(setup_code);
|
||||||
let armored_key = decrypt_setup_file(&sc, file).await?;
|
let armored_key = decrypt_setup_file(&sc, BufReader::new(file)).await?;
|
||||||
set_self_key(context, &armored_key).await?;
|
set_self_key(context, &armored_key).await?;
|
||||||
context.set_config_bool(Config::BccSelf, true).await?;
|
context.set_config_bool(Config::BccSelf, true).await?;
|
||||||
|
|
||||||
@@ -96,7 +98,7 @@ pub async fn render_setup_file(context: &Context, passphrase: &str) -> Result<St
|
|||||||
true => Some(("Autocrypt-Prefer-Encrypt", "mutual")),
|
true => Some(("Autocrypt-Prefer-Encrypt", "mutual")),
|
||||||
};
|
};
|
||||||
let private_key_asc = private_key.to_asc(ac_headers);
|
let private_key_asc = private_key.to_asc(ac_headers);
|
||||||
let encr = pgp::symm_encrypt(passphrase, private_key_asc.as_bytes())
|
let encr = pgp::symm_encrypt(passphrase, private_key_asc.into_bytes())
|
||||||
.await?
|
.await?
|
||||||
.replace('\n', "\r\n");
|
.replace('\n', "\r\n");
|
||||||
|
|
||||||
@@ -155,7 +157,7 @@ fn create_setup_code(_context: &Context) -> String {
|
|||||||
ret
|
ret
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn decrypt_setup_file<T: std::io::Read + std::io::Seek>(
|
async fn decrypt_setup_file<T: std::fmt::Debug + std::io::BufRead + Send + 'static>(
|
||||||
passphrase: &str,
|
passphrase: &str,
|
||||||
file: T,
|
file: T,
|
||||||
) -> Result<String> {
|
) -> Result<String> {
|
||||||
@@ -258,11 +260,10 @@ mod tests {
|
|||||||
|
|
||||||
assert!(!base64.is_empty());
|
assert!(!base64.is_empty());
|
||||||
|
|
||||||
let setup_file = S_EM_SETUPFILE.to_string();
|
let setup_file = S_EM_SETUPFILE;
|
||||||
let decrypted =
|
let decrypted = decrypt_setup_file(S_EM_SETUPCODE, setup_file.as_bytes())
|
||||||
decrypt_setup_file(S_EM_SETUPCODE, std::io::Cursor::new(setup_file.as_bytes()))
|
.await
|
||||||
.await
|
.unwrap();
|
||||||
.unwrap();
|
|
||||||
|
|
||||||
let (typ, headers, _base64) = split_armored_data(decrypted.as_bytes()).unwrap();
|
let (typ, headers, _base64) = split_armored_data(decrypted.as_bytes()).unwrap();
|
||||||
|
|
||||||
@@ -278,14 +279,13 @@ mod tests {
|
|||||||
/// "Implementations MUST NOT use plaintext in Symmetrically Encrypted Data packets".
|
/// "Implementations MUST NOT use plaintext in Symmetrically Encrypted Data packets".
|
||||||
#[tokio::test(flavor = "multi_thread", worker_threads = 2)]
|
#[tokio::test(flavor = "multi_thread", worker_threads = 2)]
|
||||||
async fn test_decrypt_plaintext_autocrypt_setup_message() {
|
async fn test_decrypt_plaintext_autocrypt_setup_message() {
|
||||||
let setup_file = S_PLAINTEXT_SETUPFILE.to_string();
|
let setup_file = S_PLAINTEXT_SETUPFILE;
|
||||||
let incorrect_setupcode = "0000-0000-0000-0000-0000-0000-0000-0000-0000";
|
let incorrect_setupcode = "0000-0000-0000-0000-0000-0000-0000-0000-0000";
|
||||||
assert!(decrypt_setup_file(
|
assert!(
|
||||||
incorrect_setupcode,
|
decrypt_setup_file(incorrect_setupcode, setup_file.as_bytes(),)
|
||||||
std::io::Cursor::new(setup_file.as_bytes()),
|
.await
|
||||||
)
|
.is_err()
|
||||||
.await
|
);
|
||||||
.is_err());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[tokio::test(flavor = "multi_thread", worker_threads = 2)]
|
#[tokio::test(flavor = "multi_thread", worker_threads = 2)]
|
||||||
|
|||||||
36
src/key.rs
36
src/key.rs
@@ -10,7 +10,7 @@ use deltachat_contact_tools::EmailAddress;
|
|||||||
use pgp::composed::Deserializable;
|
use pgp::composed::Deserializable;
|
||||||
pub use pgp::composed::{SignedPublicKey, SignedSecretKey};
|
pub use pgp::composed::{SignedPublicKey, SignedSecretKey};
|
||||||
use pgp::ser::Serialize;
|
use pgp::ser::Serialize;
|
||||||
use pgp::types::{PublicKeyTrait, SecretKeyTrait};
|
use pgp::types::{KeyDetails, KeyId, Password};
|
||||||
use rand::thread_rng;
|
use rand::thread_rng;
|
||||||
use tokio::runtime::Handle;
|
use tokio::runtime::Handle;
|
||||||
|
|
||||||
@@ -24,7 +24,7 @@ use crate::tools::{self, time_elapsed};
|
|||||||
/// This trait is implemented for rPGP's [SignedPublicKey] and
|
/// This trait is implemented for rPGP's [SignedPublicKey] and
|
||||||
/// [SignedSecretKey] types and makes working with them a little
|
/// [SignedSecretKey] types and makes working with them a little
|
||||||
/// easier in the deltachat world.
|
/// easier in the deltachat world.
|
||||||
pub(crate) trait DcKey: Serialize + Deserializable + PublicKeyTrait + Clone {
|
pub(crate) trait DcKey: Serialize + Deserializable + Clone {
|
||||||
/// Create a key from some bytes.
|
/// Create a key from some bytes.
|
||||||
fn from_slice(bytes: &[u8]) -> Result<Self> {
|
fn from_slice(bytes: &[u8]) -> Result<Self> {
|
||||||
let res = <Self as Deserializable>::from_bytes(Cursor::new(bytes));
|
let res = <Self as Deserializable>::from_bytes(Cursor::new(bytes));
|
||||||
@@ -78,7 +78,7 @@ pub(crate) trait DcKey: Serialize + Deserializable + PublicKeyTrait + Clone {
|
|||||||
let bytes = data.as_bytes();
|
let bytes = data.as_bytes();
|
||||||
let res = Self::from_armor_single(Cursor::new(bytes));
|
let res = Self::from_armor_single(Cursor::new(bytes));
|
||||||
let (key, headers) = match res {
|
let (key, headers) = match res {
|
||||||
Err(pgp::errors::Error::NoMatchingPacket) => match Self::is_private() {
|
Err(pgp::errors::Error::NoMatchingPacket { .. }) => match Self::is_private() {
|
||||||
true => bail!("No private key packet found"),
|
true => bail!("No private key packet found"),
|
||||||
false => bail!("No public key packet found"),
|
false => bail!("No public key packet found"),
|
||||||
},
|
},
|
||||||
@@ -123,11 +123,10 @@ pub(crate) trait DcKey: Serialize + Deserializable + PublicKeyTrait + Clone {
|
|||||||
fn to_asc(&self, header: Option<(&str, &str)>) -> String;
|
fn to_asc(&self, header: Option<(&str, &str)>) -> String;
|
||||||
|
|
||||||
/// The fingerprint for the key.
|
/// The fingerprint for the key.
|
||||||
fn dc_fingerprint(&self) -> Fingerprint {
|
fn dc_fingerprint(&self) -> Fingerprint;
|
||||||
PublicKeyTrait::fingerprint(self).into()
|
|
||||||
}
|
|
||||||
|
|
||||||
fn is_private() -> bool;
|
fn is_private() -> bool;
|
||||||
|
fn key_id(&self) -> KeyId;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) async fn load_self_public_key(context: &Context) -> Result<SignedPublicKey> {
|
pub(crate) async fn load_self_public_key(context: &Context) -> Result<SignedPublicKey> {
|
||||||
@@ -230,6 +229,14 @@ impl DcKey for SignedPublicKey {
|
|||||||
fn is_private() -> bool {
|
fn is_private() -> bool {
|
||||||
false
|
false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn dc_fingerprint(&self) -> Fingerprint {
|
||||||
|
self.fingerprint().into()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn key_id(&self) -> KeyId {
|
||||||
|
KeyDetails::key_id(self)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl DcKey for SignedSecretKey {
|
impl DcKey for SignedSecretKey {
|
||||||
@@ -249,6 +256,14 @@ impl DcKey for SignedSecretKey {
|
|||||||
fn is_private() -> bool {
|
fn is_private() -> bool {
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn dc_fingerprint(&self) -> Fingerprint {
|
||||||
|
self.fingerprint().into()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn key_id(&self) -> KeyId {
|
||||||
|
KeyDetails::key_id(&**self)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Deltachat extension trait for secret keys.
|
/// Deltachat extension trait for secret keys.
|
||||||
@@ -262,9 +277,14 @@ pub(crate) trait DcSecretKey {
|
|||||||
impl DcSecretKey for SignedSecretKey {
|
impl DcSecretKey for SignedSecretKey {
|
||||||
fn split_public_key(&self) -> Result<SignedPublicKey> {
|
fn split_public_key(&self) -> Result<SignedPublicKey> {
|
||||||
self.verify()?;
|
self.verify()?;
|
||||||
let unsigned_pubkey = SecretKeyTrait::public_key(self);
|
let unsigned_pubkey = self.public_key();
|
||||||
let mut rng = thread_rng();
|
let mut rng = thread_rng();
|
||||||
let signed_pubkey = unsigned_pubkey.sign(&mut rng, self, || "".into())?;
|
let signed_pubkey = unsigned_pubkey.sign(
|
||||||
|
&mut rng,
|
||||||
|
&self.primary_key,
|
||||||
|
self.primary_key.public_key(),
|
||||||
|
&Password::empty(),
|
||||||
|
)?;
|
||||||
Ok(signed_pubkey)
|
Ok(signed_pubkey)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -342,10 +342,10 @@ impl MimeMessage {
|
|||||||
let mail_raw; // Memory location for a possible decrypted message.
|
let mail_raw; // Memory location for a possible decrypted message.
|
||||||
let decrypted_msg; // Decrypted signed OpenPGP message.
|
let decrypted_msg; // Decrypted signed OpenPGP message.
|
||||||
|
|
||||||
let (mail, encrypted) =
|
let (mail, is_encrypted) =
|
||||||
match tokio::task::block_in_place(|| try_decrypt(&mail, &private_keyring)) {
|
match tokio::task::block_in_place(|| try_decrypt(&mail, &private_keyring)) {
|
||||||
Ok(Some(msg)) => {
|
Ok(Some(mut msg)) => {
|
||||||
mail_raw = msg.get_content()?.unwrap_or_default();
|
mail_raw = msg.as_data_vec().unwrap_or_default();
|
||||||
|
|
||||||
let decrypted_mail = mailparse::parse_mail(&mail_raw)?;
|
let decrypted_mail = mailparse::parse_mail(&mail_raw)?;
|
||||||
if std::env::var(crate::DCC_MIME_DEBUG).is_ok() {
|
if std::env::var(crate::DCC_MIME_DEBUG).is_ok() {
|
||||||
@@ -434,7 +434,7 @@ impl MimeMessage {
|
|||||||
signatures.extend(signatures_detached);
|
signatures.extend(signatures_detached);
|
||||||
content
|
content
|
||||||
});
|
});
|
||||||
if let (Ok(mail), true) = (mail, encrypted) {
|
if let (Ok(mail), true) = (mail, is_encrypted) {
|
||||||
if !signatures.is_empty() {
|
if !signatures.is_empty() {
|
||||||
// Remove unsigned opportunistically protected headers from messages considered
|
// Remove unsigned opportunistically protected headers from messages considered
|
||||||
// Autocrypt-encrypted / displayed with padlock.
|
// Autocrypt-encrypted / displayed with padlock.
|
||||||
@@ -529,7 +529,7 @@ impl MimeMessage {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if !encrypted {
|
if !is_encrypted {
|
||||||
signatures.clear();
|
signatures.clear();
|
||||||
}
|
}
|
||||||
if let Some(peerstate) = &mut peerstate {
|
if let Some(peerstate) = &mut peerstate {
|
||||||
|
|||||||
218
src/pgp.rs
218
src/pgp.rs
@@ -1,19 +1,22 @@
|
|||||||
//! OpenPGP helper module using [rPGP facilities](https://github.com/rpgp/rpgp).
|
//! OpenPGP helper module using [rPGP facilities](https://github.com/rpgp/rpgp).
|
||||||
|
|
||||||
use std::collections::{BTreeMap, HashSet};
|
use std::collections::{BTreeMap, HashSet};
|
||||||
use std::io::Cursor;
|
use std::io::{BufRead, Cursor};
|
||||||
|
|
||||||
use anyhow::{bail, Context as _, Result};
|
use anyhow::{Context as _, Result};
|
||||||
|
use chrono::SubsecRound;
|
||||||
use deltachat_contact_tools::EmailAddress;
|
use deltachat_contact_tools::EmailAddress;
|
||||||
use pgp::armor::BlockType;
|
use pgp::armor::BlockType;
|
||||||
use pgp::composed::{
|
use pgp::composed::{
|
||||||
Deserializable, KeyType as PgpKeyType, Message, SecretKeyParamsBuilder, SignedPublicKey,
|
ArmorOptions, Deserializable, KeyType as PgpKeyType, Message, MessageBuilder,
|
||||||
SignedPublicSubKey, SignedSecretKey, StandaloneSignature, SubkeyParamsBuilder,
|
SecretKeyParamsBuilder, SignedPublicKey, SignedPublicSubKey, SignedSecretKey,
|
||||||
|
StandaloneSignature, SubkeyParamsBuilder, TheRing,
|
||||||
};
|
};
|
||||||
use pgp::crypto::ecc_curve::ECCCurve;
|
use pgp::crypto::ecc_curve::ECCCurve;
|
||||||
use pgp::crypto::hash::HashAlgorithm;
|
use pgp::crypto::hash::HashAlgorithm;
|
||||||
use pgp::crypto::sym::SymmetricKeyAlgorithm;
|
use pgp::crypto::sym::SymmetricKeyAlgorithm;
|
||||||
use pgp::types::{CompressionAlgorithm, PublicKeyTrait, StringToKey};
|
use pgp::packet::{SignatureConfig, SignatureType, Subpacket, SubpacketData};
|
||||||
|
use pgp::types::{CompressionAlgorithm, KeyDetails, Password, PublicKeyTrait, StringToKey};
|
||||||
use rand::thread_rng;
|
use rand::thread_rng;
|
||||||
use tokio::runtime::Handle;
|
use tokio::runtime::Handle;
|
||||||
|
|
||||||
@@ -28,7 +31,7 @@ pub const HEADER_SETUPCODE: &str = "passphrase-begin";
|
|||||||
const SYMMETRIC_KEY_ALGORITHM: SymmetricKeyAlgorithm = SymmetricKeyAlgorithm::AES128;
|
const SYMMETRIC_KEY_ALGORITHM: SymmetricKeyAlgorithm = SymmetricKeyAlgorithm::AES128;
|
||||||
|
|
||||||
/// Preferred cryptographic hash.
|
/// Preferred cryptographic hash.
|
||||||
const HASH_ALGORITHM: HashAlgorithm = HashAlgorithm::SHA2_256;
|
const HASH_ALGORITHM: HashAlgorithm = HashAlgorithm::Sha256;
|
||||||
|
|
||||||
/// Split data from PGP Armored Data as defined in <https://tools.ietf.org/html/rfc4880#section-6.2>.
|
/// Split data from PGP Armored Data as defined in <https://tools.ietf.org/html/rfc4880#section-6.2>.
|
||||||
///
|
///
|
||||||
@@ -91,7 +94,7 @@ impl KeyPair {
|
|||||||
/// Both secret and public key consist of signing primary key and encryption subkey
|
/// Both secret and public key consist of signing primary key and encryption subkey
|
||||||
/// as [described in the Autocrypt standard](https://autocrypt.org/level1.html#openpgp-based-key-data).
|
/// as [described in the Autocrypt standard](https://autocrypt.org/level1.html#openpgp-based-key-data).
|
||||||
pub(crate) fn create_keypair(addr: EmailAddress) -> Result<KeyPair> {
|
pub(crate) fn create_keypair(addr: EmailAddress) -> Result<KeyPair> {
|
||||||
let signing_key_type = PgpKeyType::EdDSALegacy;
|
let signing_key_type = PgpKeyType::Ed25519Legacy;
|
||||||
let encryption_key_type = PgpKeyType::ECDH(ECCCurve::Curve25519);
|
let encryption_key_type = PgpKeyType::ECDH(ECCCurve::Curve25519);
|
||||||
|
|
||||||
let user_id = format!("<{addr}>");
|
let user_id = format!("<{addr}>");
|
||||||
@@ -107,11 +110,10 @@ pub(crate) fn create_keypair(addr: EmailAddress) -> Result<KeyPair> {
|
|||||||
SymmetricKeyAlgorithm::AES128,
|
SymmetricKeyAlgorithm::AES128,
|
||||||
])
|
])
|
||||||
.preferred_hash_algorithms(smallvec![
|
.preferred_hash_algorithms(smallvec![
|
||||||
HashAlgorithm::SHA2_256,
|
HashAlgorithm::Sha256,
|
||||||
HashAlgorithm::SHA2_384,
|
HashAlgorithm::Sha384,
|
||||||
HashAlgorithm::SHA2_512,
|
HashAlgorithm::Sha512,
|
||||||
HashAlgorithm::SHA2_224,
|
HashAlgorithm::Sha224,
|
||||||
HashAlgorithm::SHA1,
|
|
||||||
])
|
])
|
||||||
.preferred_compression_algorithms(smallvec![
|
.preferred_compression_algorithms(smallvec![
|
||||||
CompressionAlgorithm::ZLIB,
|
CompressionAlgorithm::ZLIB,
|
||||||
@@ -132,7 +134,7 @@ pub(crate) fn create_keypair(addr: EmailAddress) -> Result<KeyPair> {
|
|||||||
let secret_key = key_params
|
let secret_key = key_params
|
||||||
.generate(&mut rng)
|
.generate(&mut rng)
|
||||||
.context("failed to generate the key")?
|
.context("failed to generate the key")?
|
||||||
.sign(&mut rng, || "".into())
|
.sign(&mut rng, &Password::empty())
|
||||||
.context("failed to sign secret key")?;
|
.context("failed to sign secret key")?;
|
||||||
secret_key
|
secret_key
|
||||||
.verify()
|
.verify()
|
||||||
@@ -160,55 +162,73 @@ fn select_pk_for_encryption(key: &SignedPublicKey) -> Option<&SignedPublicSubKey
|
|||||||
/// Encrypts `plain` text using `public_keys_for_encryption`
|
/// Encrypts `plain` text using `public_keys_for_encryption`
|
||||||
/// and signs it using `private_key_for_signing`.
|
/// and signs it using `private_key_for_signing`.
|
||||||
pub async fn pk_encrypt(
|
pub async fn pk_encrypt(
|
||||||
plain: &[u8],
|
plain: Vec<u8>,
|
||||||
public_keys_for_encryption: Vec<SignedPublicKey>,
|
public_keys_for_encryption: Vec<SignedPublicKey>,
|
||||||
private_key_for_signing: Option<SignedSecretKey>,
|
private_key_for_signing: Option<SignedSecretKey>,
|
||||||
compress: bool,
|
compress: bool,
|
||||||
) -> Result<String> {
|
) -> Result<String> {
|
||||||
let lit_msg = Message::new_literal_bytes("", plain);
|
|
||||||
|
|
||||||
Handle::current()
|
Handle::current()
|
||||||
.spawn_blocking(move || {
|
.spawn_blocking(move || {
|
||||||
let pkeys: Vec<&SignedPublicSubKey> = public_keys_for_encryption
|
|
||||||
.iter()
|
|
||||||
.filter_map(select_pk_for_encryption)
|
|
||||||
.collect();
|
|
||||||
|
|
||||||
let mut rng = thread_rng();
|
let mut rng = thread_rng();
|
||||||
|
|
||||||
let encrypted_msg = if let Some(ref skey) = private_key_for_signing {
|
let pkeys = public_keys_for_encryption
|
||||||
let signed_msg = lit_msg.sign(&mut rng, skey, || "".into(), HASH_ALGORITHM)?;
|
.iter()
|
||||||
let compressed_msg = if compress {
|
.filter_map(select_pk_for_encryption);
|
||||||
signed_msg.compress(CompressionAlgorithm::ZLIB)?
|
|
||||||
} else {
|
|
||||||
signed_msg
|
|
||||||
};
|
|
||||||
compressed_msg.encrypt_to_keys_seipdv1(&mut rng, SYMMETRIC_KEY_ALGORITHM, &pkeys)?
|
|
||||||
} else {
|
|
||||||
lit_msg.encrypt_to_keys_seipdv1(&mut rng, SYMMETRIC_KEY_ALGORITHM, &pkeys)?
|
|
||||||
};
|
|
||||||
|
|
||||||
let encoded_msg = encrypted_msg.to_armored_string(Default::default())?;
|
let msg = MessageBuilder::from_bytes("", plain);
|
||||||
|
let mut msg = msg.seipd_v1(&mut rng, SYMMETRIC_KEY_ALGORITHM);
|
||||||
|
for pkey in pkeys {
|
||||||
|
msg.encrypt_to_key(&mut rng, &pkey)?;
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(ref skey) = private_key_for_signing {
|
||||||
|
msg.sign(&**skey, Password::empty(), HASH_ALGORITHM);
|
||||||
|
if compress {
|
||||||
|
msg.compression(CompressionAlgorithm::ZLIB);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let encoded_msg = msg.to_armored_string(&mut rng, Default::default())?;
|
||||||
|
|
||||||
Ok(encoded_msg)
|
Ok(encoded_msg)
|
||||||
})
|
})
|
||||||
.await?
|
.await?
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Signs `plain` text using `private_key_for_signing`.
|
/// Produces a detached signature for `plain` text using `private_key_for_signing`.
|
||||||
pub fn pk_calc_signature(
|
pub fn pk_calc_signature(
|
||||||
plain: &[u8],
|
plain: Vec<u8>,
|
||||||
private_key_for_signing: &SignedSecretKey,
|
private_key_for_signing: &SignedSecretKey,
|
||||||
) -> Result<String> {
|
) -> Result<String> {
|
||||||
let mut rng = thread_rng();
|
let rng = thread_rng();
|
||||||
let msg = Message::new_literal_bytes("", plain).sign(
|
|
||||||
&mut rng,
|
let mut config = SignatureConfig::from_key(
|
||||||
private_key_for_signing,
|
rng,
|
||||||
|| "".into(),
|
&private_key_for_signing.primary_key,
|
||||||
HASH_ALGORITHM,
|
SignatureType::Binary,
|
||||||
)?;
|
)?;
|
||||||
let signature = msg.into_signature().to_armored_string(Default::default())?;
|
|
||||||
Ok(signature)
|
config.hashed_subpackets = vec![
|
||||||
|
Subpacket::regular(SubpacketData::IssuerFingerprint(
|
||||||
|
private_key_for_signing.fingerprint(),
|
||||||
|
))?,
|
||||||
|
Subpacket::critical(SubpacketData::SignatureCreationTime(
|
||||||
|
chrono::Utc::now().trunc_subsecs(0),
|
||||||
|
))?,
|
||||||
|
];
|
||||||
|
config.unhashed_subpackets = vec![Subpacket::regular(SubpacketData::Issuer(
|
||||||
|
private_key_for_signing.key_id(),
|
||||||
|
))?];
|
||||||
|
|
||||||
|
let signature = config.sign(
|
||||||
|
&private_key_for_signing.primary_key,
|
||||||
|
&Password::empty(),
|
||||||
|
plain.as_slice(),
|
||||||
|
)?;
|
||||||
|
|
||||||
|
let sig = StandaloneSignature::new(signature);
|
||||||
|
|
||||||
|
Ok(sig.to_armored_string(ArmorOptions::default())?)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Decrypts the message with keys from the private key keyring.
|
/// Decrypts the message with keys from the private key keyring.
|
||||||
@@ -218,16 +238,27 @@ pub fn pk_calc_signature(
|
|||||||
pub fn pk_decrypt(
|
pub fn pk_decrypt(
|
||||||
ctext: Vec<u8>,
|
ctext: Vec<u8>,
|
||||||
private_keys_for_decryption: &[SignedSecretKey],
|
private_keys_for_decryption: &[SignedSecretKey],
|
||||||
) -> Result<pgp::composed::Message> {
|
) -> Result<pgp::composed::Message<'static>> {
|
||||||
let cursor = Cursor::new(ctext);
|
let cursor = Cursor::new(ctext);
|
||||||
let (msg, _headers) = Message::from_armor_single(cursor)?;
|
let (msg, _headers) = Message::from_armor(cursor)?;
|
||||||
|
|
||||||
let skeys: Vec<&SignedSecretKey> = private_keys_for_decryption.iter().collect();
|
let skeys: Vec<&SignedSecretKey> = private_keys_for_decryption.iter().collect();
|
||||||
|
let empty_pw = Password::empty();
|
||||||
|
|
||||||
let (msg, _key_ids) = msg.decrypt(|| "".into(), &skeys[..])?;
|
let ring = TheRing {
|
||||||
|
secret_keys: skeys,
|
||||||
|
key_passwords: vec![&empty_pw],
|
||||||
|
message_password: vec![],
|
||||||
|
session_keys: vec![],
|
||||||
|
allow_legacy: false,
|
||||||
|
};
|
||||||
|
let (msg, ring_result) = msg.decrypt_the_ring(ring, true)?;
|
||||||
|
anyhow::ensure!(
|
||||||
|
!ring_result.secret_keys.is_empty(),
|
||||||
|
"decryption failed, no matching secret keys"
|
||||||
|
);
|
||||||
|
|
||||||
// get_content() will decompress the message if needed,
|
// remove one layer of compression
|
||||||
// but this avoids decompressing it again to check signatures
|
|
||||||
let msg = msg.decompress()?;
|
let msg = msg.decompress()?;
|
||||||
|
|
||||||
Ok(msg)
|
Ok(msg)
|
||||||
@@ -243,9 +274,9 @@ pub fn valid_signature_fingerprints(
|
|||||||
public_keys_for_validation: &[SignedPublicKey],
|
public_keys_for_validation: &[SignedPublicKey],
|
||||||
) -> Result<HashSet<Fingerprint>> {
|
) -> Result<HashSet<Fingerprint>> {
|
||||||
let mut ret_signature_fingerprints: HashSet<Fingerprint> = Default::default();
|
let mut ret_signature_fingerprints: HashSet<Fingerprint> = Default::default();
|
||||||
if let signed_msg @ pgp::composed::Message::Signed { .. } = msg {
|
if msg.is_signed() {
|
||||||
for pkey in public_keys_for_validation {
|
for pkey in public_keys_for_validation {
|
||||||
if signed_msg.verify(&pkey.primary_key).is_ok() {
|
if msg.verify(&pkey.primary_key).is_ok() {
|
||||||
let fp = pkey.dc_fingerprint();
|
let fp = pkey.dc_fingerprint();
|
||||||
ret_signature_fingerprints.insert(fp);
|
ret_signature_fingerprints.insert(fp);
|
||||||
}
|
}
|
||||||
@@ -274,21 +305,17 @@ pub fn pk_validate(
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Symmetric encryption.
|
/// Symmetric encryption.
|
||||||
pub async fn symm_encrypt(passphrase: &str, plain: &[u8]) -> Result<String> {
|
pub async fn symm_encrypt(passphrase: &str, plain: Vec<u8>) -> Result<String> {
|
||||||
let lit_msg = Message::new_literal_bytes("", plain);
|
let passphrase = Password::from(passphrase.to_string());
|
||||||
let passphrase = passphrase.to_string();
|
|
||||||
|
|
||||||
tokio::task::spawn_blocking(move || {
|
tokio::task::spawn_blocking(move || {
|
||||||
let mut rng = thread_rng();
|
let mut rng = thread_rng();
|
||||||
let s2k = StringToKey::new_default(&mut rng);
|
let s2k = StringToKey::new_default(&mut rng);
|
||||||
let msg = lit_msg.encrypt_with_password_seipdv1(
|
let builder = MessageBuilder::from_bytes("", plain);
|
||||||
&mut rng,
|
let mut builder = builder.seipd_v1(&mut rng, SYMMETRIC_KEY_ALGORITHM);
|
||||||
s2k,
|
builder.encrypt_with_password(s2k, &passphrase)?;
|
||||||
SYMMETRIC_KEY_ALGORITHM,
|
|
||||||
|| passphrase,
|
|
||||||
)?;
|
|
||||||
|
|
||||||
let encoded_msg = msg.to_armored_string(Default::default())?;
|
let encoded_msg = builder.to_armored_string(&mut rng, Default::default())?;
|
||||||
|
|
||||||
Ok(encoded_msg)
|
Ok(encoded_msg)
|
||||||
})
|
})
|
||||||
@@ -296,20 +323,18 @@ pub async fn symm_encrypt(passphrase: &str, plain: &[u8]) -> Result<String> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Symmetric decryption.
|
/// Symmetric decryption.
|
||||||
pub async fn symm_decrypt<T: std::io::Read + std::io::Seek>(
|
pub async fn symm_decrypt<T: BufRead + std::fmt::Debug + 'static + Send>(
|
||||||
passphrase: &str,
|
passphrase: &str,
|
||||||
ctext: T,
|
ctext: T,
|
||||||
) -> Result<Vec<u8>> {
|
) -> Result<Vec<u8>> {
|
||||||
let (enc_msg, _) = Message::from_armor_single(ctext)?;
|
|
||||||
|
|
||||||
let passphrase = passphrase.to_string();
|
let passphrase = passphrase.to_string();
|
||||||
tokio::task::spawn_blocking(move || {
|
tokio::task::spawn_blocking(move || {
|
||||||
let msg = enc_msg.decrypt_with_password(|| passphrase)?;
|
let (enc_msg, _) = Message::from_armor(ctext)?;
|
||||||
|
let password = Password::from(passphrase);
|
||||||
|
|
||||||
match msg.get_content()? {
|
let msg = enc_msg.decrypt_with_password(&password)?;
|
||||||
Some(content) => Ok(content),
|
let res = msg.decompress()?.as_data_vec()?;
|
||||||
None => bail!("Decrypted message is empty"),
|
Ok(res)
|
||||||
}
|
|
||||||
})
|
})
|
||||||
.await?
|
.await?
|
||||||
}
|
}
|
||||||
@@ -322,16 +347,21 @@ mod tests {
|
|||||||
use super::*;
|
use super::*;
|
||||||
use crate::test_utils::{alice_keypair, bob_keypair};
|
use crate::test_utils::{alice_keypair, bob_keypair};
|
||||||
|
|
||||||
fn pk_decrypt_and_validate(
|
fn pk_decrypt_and_validate<'a>(
|
||||||
ctext: Vec<u8>,
|
ctext: &'a [u8],
|
||||||
private_keys_for_decryption: &[SignedSecretKey],
|
private_keys_for_decryption: &'a [SignedSecretKey],
|
||||||
public_keys_for_validation: &[SignedPublicKey],
|
public_keys_for_validation: &[SignedPublicKey],
|
||||||
) -> Result<(pgp::composed::Message, HashSet<Fingerprint>)> {
|
) -> Result<(
|
||||||
let msg = pk_decrypt(ctext, private_keys_for_decryption)?;
|
pgp::composed::Message<'static>,
|
||||||
|
HashSet<Fingerprint>,
|
||||||
|
Vec<u8>,
|
||||||
|
)> {
|
||||||
|
let mut msg = pk_decrypt(ctext.to_vec(), private_keys_for_decryption)?;
|
||||||
|
let content = msg.as_data_vec()?;
|
||||||
let ret_signature_fingerprints =
|
let ret_signature_fingerprints =
|
||||||
valid_signature_fingerprints(&msg, public_keys_for_validation)?;
|
valid_signature_fingerprints(&msg, public_keys_for_validation)?;
|
||||||
|
|
||||||
Ok((msg, ret_signature_fingerprints))
|
Ok((msg, ret_signature_fingerprints, content))
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
@@ -407,7 +437,7 @@ mod tests {
|
|||||||
let compress = true;
|
let compress = true;
|
||||||
|
|
||||||
pk_encrypt(
|
pk_encrypt(
|
||||||
CLEARTEXT,
|
CLEARTEXT.to_vec(),
|
||||||
keyring,
|
keyring,
|
||||||
Some(KEYS.alice_secret.clone()),
|
Some(KEYS.alice_secret.clone()),
|
||||||
compress,
|
compress,
|
||||||
@@ -425,7 +455,7 @@ mod tests {
|
|||||||
let keyring = vec![KEYS.alice_public.clone(), KEYS.bob_public.clone()];
|
let keyring = vec![KEYS.alice_public.clone(), KEYS.bob_public.clone()];
|
||||||
let compress = true;
|
let compress = true;
|
||||||
|
|
||||||
pk_encrypt(CLEARTEXT, keyring, None, compress)
|
pk_encrypt(CLEARTEXT.to_vec(), keyring, None, compress)
|
||||||
.await
|
.await
|
||||||
.unwrap()
|
.unwrap()
|
||||||
})
|
})
|
||||||
@@ -453,35 +483,34 @@ mod tests {
|
|||||||
// Check decrypting as Alice
|
// Check decrypting as Alice
|
||||||
let decrypt_keyring = vec![KEYS.alice_secret.clone()];
|
let decrypt_keyring = vec![KEYS.alice_secret.clone()];
|
||||||
let sig_check_keyring = vec![KEYS.alice_public.clone()];
|
let sig_check_keyring = vec![KEYS.alice_public.clone()];
|
||||||
let (msg, valid_signatures) = pk_decrypt_and_validate(
|
let (_msg, valid_signatures, content) = pk_decrypt_and_validate(
|
||||||
ctext_signed().await.as_bytes().to_vec(),
|
ctext_signed().await.as_bytes(),
|
||||||
&decrypt_keyring,
|
&decrypt_keyring,
|
||||||
&sig_check_keyring,
|
&sig_check_keyring,
|
||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
assert_eq!(msg.get_content().unwrap().unwrap(), CLEARTEXT);
|
assert_eq!(content, CLEARTEXT);
|
||||||
assert_eq!(valid_signatures.len(), 1);
|
assert_eq!(valid_signatures.len(), 1);
|
||||||
|
|
||||||
// Check decrypting as Bob
|
// Check decrypting as Bob
|
||||||
let decrypt_keyring = vec![KEYS.bob_secret.clone()];
|
let decrypt_keyring = vec![KEYS.bob_secret.clone()];
|
||||||
let sig_check_keyring = vec![KEYS.alice_public.clone()];
|
let sig_check_keyring = vec![KEYS.alice_public.clone()];
|
||||||
let (msg, valid_signatures) = pk_decrypt_and_validate(
|
let (_msg, valid_signatures, content) = pk_decrypt_and_validate(
|
||||||
ctext_signed().await.as_bytes().to_vec(),
|
ctext_signed().await.as_bytes(),
|
||||||
&decrypt_keyring,
|
&decrypt_keyring,
|
||||||
&sig_check_keyring,
|
&sig_check_keyring,
|
||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
assert_eq!(msg.get_content().unwrap().unwrap(), CLEARTEXT);
|
assert_eq!(content, CLEARTEXT);
|
||||||
assert_eq!(valid_signatures.len(), 1);
|
assert_eq!(valid_signatures.len(), 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[tokio::test(flavor = "multi_thread", worker_threads = 2)]
|
#[tokio::test(flavor = "multi_thread", worker_threads = 2)]
|
||||||
async fn test_decrypt_no_sig_check() {
|
async fn test_decrypt_no_sig_check() {
|
||||||
let keyring = vec![KEYS.alice_secret.clone()];
|
let keyring = vec![KEYS.alice_secret.clone()];
|
||||||
let (msg, valid_signatures) =
|
let (_msg, valid_signatures, content) =
|
||||||
pk_decrypt_and_validate(ctext_signed().await.as_bytes().to_vec(), &keyring, &[])
|
pk_decrypt_and_validate(ctext_signed().await.as_bytes(), &keyring, &[]).unwrap();
|
||||||
.unwrap();
|
assert_eq!(content, CLEARTEXT);
|
||||||
assert_eq!(msg.get_content().unwrap().unwrap(), CLEARTEXT);
|
|
||||||
assert_eq!(valid_signatures.len(), 0);
|
assert_eq!(valid_signatures.len(), 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -490,26 +519,23 @@ mod tests {
|
|||||||
// The validation does not have the public key of the signer.
|
// The validation does not have the public key of the signer.
|
||||||
let decrypt_keyring = vec![KEYS.bob_secret.clone()];
|
let decrypt_keyring = vec![KEYS.bob_secret.clone()];
|
||||||
let sig_check_keyring = vec![KEYS.bob_public.clone()];
|
let sig_check_keyring = vec![KEYS.bob_public.clone()];
|
||||||
let (msg, valid_signatures) = pk_decrypt_and_validate(
|
let (_msg, valid_signatures, content) = pk_decrypt_and_validate(
|
||||||
ctext_signed().await.as_bytes().to_vec(),
|
ctext_signed().await.as_bytes(),
|
||||||
&decrypt_keyring,
|
&decrypt_keyring,
|
||||||
&sig_check_keyring,
|
&sig_check_keyring,
|
||||||
)
|
)
|
||||||
.unwrap();
|
.unwrap();
|
||||||
assert_eq!(msg.get_content().unwrap().unwrap(), CLEARTEXT);
|
assert_eq!(content, CLEARTEXT);
|
||||||
assert_eq!(valid_signatures.len(), 0);
|
assert_eq!(valid_signatures.len(), 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[tokio::test(flavor = "multi_thread", worker_threads = 2)]
|
#[tokio::test(flavor = "multi_thread", worker_threads = 2)]
|
||||||
async fn test_decrypt_unsigned() {
|
async fn test_decrypt_unsigned() {
|
||||||
let decrypt_keyring = vec![KEYS.bob_secret.clone()];
|
let decrypt_keyring = vec![KEYS.bob_secret.clone()];
|
||||||
let (msg, valid_signatures) = pk_decrypt_and_validate(
|
let (_msg, valid_signatures, content) =
|
||||||
ctext_unsigned().await.as_bytes().to_vec(),
|
pk_decrypt_and_validate(ctext_unsigned().await.as_bytes(), &decrypt_keyring, &[])
|
||||||
&decrypt_keyring,
|
.unwrap();
|
||||||
&[],
|
assert_eq!(content, CLEARTEXT);
|
||||||
)
|
|
||||||
.unwrap();
|
|
||||||
assert_eq!(msg.get_content().unwrap().unwrap(), CLEARTEXT);
|
|
||||||
assert_eq!(valid_signatures.len(), 0);
|
assert_eq!(valid_signatures.len(), 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
16
src/push.rs
16
src/push.rs
@@ -11,9 +11,8 @@ use std::sync::Arc;
|
|||||||
|
|
||||||
use anyhow::{Context as _, Result};
|
use anyhow::{Context as _, Result};
|
||||||
use base64::Engine as _;
|
use base64::Engine as _;
|
||||||
use pgp::crypto::aead::AeadAlgorithm;
|
use pgp::crypto::aead::{AeadAlgorithm, ChunkSize};
|
||||||
use pgp::crypto::sym::SymmetricKeyAlgorithm;
|
use pgp::crypto::sym::SymmetricKeyAlgorithm;
|
||||||
use pgp::ser::Serialize;
|
|
||||||
use rand::thread_rng;
|
use rand::thread_rng;
|
||||||
use tokio::sync::RwLock;
|
use tokio::sync::RwLock;
|
||||||
|
|
||||||
@@ -81,18 +80,17 @@ pub(crate) fn encrypt_device_token(device_token: &str) -> Result<String> {
|
|||||||
.first()
|
.first()
|
||||||
.context("No encryption subkey found")?;
|
.context("No encryption subkey found")?;
|
||||||
let padded_device_token = pad_device_token(device_token);
|
let padded_device_token = pad_device_token(device_token);
|
||||||
let literal_message = pgp::composed::Message::new_literal("", &padded_device_token);
|
|
||||||
let mut rng = thread_rng();
|
let mut rng = thread_rng();
|
||||||
let chunk_size = 8;
|
|
||||||
|
|
||||||
let encrypted_message = literal_message.encrypt_to_keys_seipdv2(
|
let mut msg = pgp::composed::MessageBuilder::from_bytes("", padded_device_token).seipd_v2(
|
||||||
&mut rng,
|
&mut rng,
|
||||||
SymmetricKeyAlgorithm::AES128,
|
SymmetricKeyAlgorithm::AES128,
|
||||||
AeadAlgorithm::Ocb,
|
AeadAlgorithm::Ocb,
|
||||||
chunk_size,
|
ChunkSize::C8KiB,
|
||||||
&[&encryption_subkey],
|
);
|
||||||
)?;
|
msg.encrypt_to_key(&mut rng, &encryption_subkey)?;
|
||||||
let encoded_message = encrypted_message.to_bytes()?;
|
let encoded_message = msg.to_vec(&mut rng)?;
|
||||||
|
|
||||||
Ok(format!(
|
Ok(format!(
|
||||||
"openpgp:{}",
|
"openpgp:{}",
|
||||||
base64::engine::general_purpose::STANDARD.encode(encoded_message)
|
base64::engine::general_purpose::STANDARD.encode(encoded_message)
|
||||||
|
|||||||
Reference in New Issue
Block a user