1
1
//! OpenPGP helper module using [rPGP facilities](https://github.com/rpgp/rpgp).
2
2
3
3
use std:: collections:: { BTreeMap , HashSet } ;
4
- use std:: io;
5
4
use std:: io:: Cursor ;
6
5
7
6
use anyhow:: { bail, Context as _, Result } ;
@@ -14,8 +13,8 @@ use pgp::composed::{
14
13
use pgp:: crypto:: ecc_curve:: ECCCurve ;
15
14
use pgp:: crypto:: hash:: HashAlgorithm ;
16
15
use pgp:: crypto:: sym:: SymmetricKeyAlgorithm ;
17
- use pgp:: types:: { CompressionAlgorithm , PublicKeyTrait , SignatureBytes , StringToKey } ;
18
- use rand:: { thread_rng, CryptoRng , Rng } ;
16
+ use pgp:: types:: { CompressionAlgorithm , PublicKeyTrait , StringToKey } ;
17
+ use rand:: thread_rng;
19
18
use tokio:: runtime:: Handle ;
20
19
21
20
use crate :: key:: { DcKey , Fingerprint } ;
@@ -31,95 +30,6 @@ const SYMMETRIC_KEY_ALGORITHM: SymmetricKeyAlgorithm = SymmetricKeyAlgorithm::AE
31
30
/// Preferred cryptographic hash.
32
31
const HASH_ALGORITHM : HashAlgorithm = HashAlgorithm :: SHA2_256 ;
33
32
34
- /// A wrapper for rPGP public key types
35
- #[ derive( Debug ) ]
36
- enum SignedPublicKeyOrSubkey < ' a > {
37
- Key ( & ' a SignedPublicKey ) ,
38
- Subkey ( & ' a SignedPublicSubKey ) ,
39
- }
40
-
41
- impl PublicKeyTrait for SignedPublicKeyOrSubkey < ' _ > {
42
- fn version ( & self ) -> pgp:: types:: KeyVersion {
43
- match self {
44
- Self :: Key ( k) => k. version ( ) ,
45
- Self :: Subkey ( k) => k. version ( ) ,
46
- }
47
- }
48
-
49
- fn fingerprint ( & self ) -> pgp:: types:: Fingerprint {
50
- match self {
51
- Self :: Key ( k) => k. fingerprint ( ) ,
52
- Self :: Subkey ( k) => k. fingerprint ( ) ,
53
- }
54
- }
55
-
56
- fn key_id ( & self ) -> pgp:: types:: KeyId {
57
- match self {
58
- Self :: Key ( k) => k. key_id ( ) ,
59
- Self :: Subkey ( k) => k. key_id ( ) ,
60
- }
61
- }
62
-
63
- fn algorithm ( & self ) -> pgp:: crypto:: public_key:: PublicKeyAlgorithm {
64
- match self {
65
- Self :: Key ( k) => k. algorithm ( ) ,
66
- Self :: Subkey ( k) => k. algorithm ( ) ,
67
- }
68
- }
69
-
70
- fn created_at ( & self ) -> & chrono:: DateTime < chrono:: Utc > {
71
- match self {
72
- Self :: Key ( k) => k. created_at ( ) ,
73
- Self :: Subkey ( k) => k. created_at ( ) ,
74
- }
75
- }
76
-
77
- fn expiration ( & self ) -> Option < u16 > {
78
- match self {
79
- Self :: Key ( k) => k. expiration ( ) ,
80
- Self :: Subkey ( k) => k. expiration ( ) ,
81
- }
82
- }
83
-
84
- fn verify_signature (
85
- & self ,
86
- hash : HashAlgorithm ,
87
- data : & [ u8 ] ,
88
- sig : & SignatureBytes ,
89
- ) -> pgp:: errors:: Result < ( ) > {
90
- match self {
91
- Self :: Key ( k) => k. verify_signature ( hash, data, sig) ,
92
- Self :: Subkey ( k) => k. verify_signature ( hash, data, sig) ,
93
- }
94
- }
95
-
96
- fn encrypt < R : Rng + CryptoRng > (
97
- & self ,
98
- rng : R ,
99
- plain : & [ u8 ] ,
100
- typ : pgp:: types:: EskType ,
101
- ) -> pgp:: errors:: Result < pgp:: types:: PkeskBytes > {
102
- match self {
103
- Self :: Key ( k) => k. encrypt ( rng, plain, typ) ,
104
- Self :: Subkey ( k) => k. encrypt ( rng, plain, typ) ,
105
- }
106
- }
107
-
108
- fn serialize_for_hashing ( & self , writer : & mut impl io:: Write ) -> pgp:: errors:: Result < ( ) > {
109
- match self {
110
- Self :: Key ( k) => k. serialize_for_hashing ( writer) ,
111
- Self :: Subkey ( k) => k. serialize_for_hashing ( writer) ,
112
- }
113
- }
114
-
115
- fn public_params ( & self ) -> & pgp:: types:: PublicParams {
116
- match self {
117
- Self :: Key ( k) => k. public_params ( ) ,
118
- Self :: Subkey ( k) => k. public_params ( ) ,
119
- }
120
- }
121
- }
122
-
123
33
/// Split data from PGP Armored Data as defined in <https://tools.ietf.org/html/rfc4880#section-6.2>.
124
34
///
125
35
/// Returns (type, headers, base64 encoded body).
@@ -236,28 +146,15 @@ pub(crate) fn create_keypair(addr: EmailAddress) -> Result<KeyPair> {
236
146
Ok ( key_pair)
237
147
}
238
148
239
- /// Select public key or subkey to use for encryption.
149
+ /// Selects a subkey of the public key to use for encryption.
240
150
///
241
- /// First, tries to use subkeys. If none of the subkeys are suitable
242
- /// for encryption, tries to use primary key. Returns `None` if the public
243
- /// key cannot be used for encryption.
151
+ /// Returns `None` if the public key cannot be used for encryption.
244
152
///
245
153
/// TODO: take key flags and expiration dates into account
246
- fn select_pk_for_encryption ( key : & SignedPublicKey ) -> Option < SignedPublicKeyOrSubkey > {
154
+ fn select_pk_for_encryption ( key : & SignedPublicKey ) -> Option < & SignedPublicSubKey > {
247
155
key. public_subkeys
248
156
. iter ( )
249
157
. find ( |subkey| subkey. is_encryption_key ( ) )
250
- . map_or_else (
251
- || {
252
- // No usable subkey found, try primary key
253
- if key. is_encryption_key ( ) {
254
- Some ( SignedPublicKeyOrSubkey :: Key ( key) )
255
- } else {
256
- None
257
- }
258
- } ,
259
- |subkey| Some ( SignedPublicKeyOrSubkey :: Subkey ( subkey) ) ,
260
- )
261
158
}
262
159
263
160
/// Encrypts `plain` text using `public_keys_for_encryption`
@@ -272,11 +169,10 @@ pub async fn pk_encrypt(
272
169
273
170
Handle :: current ( )
274
171
. spawn_blocking ( move || {
275
- let pkeys: Vec < SignedPublicKeyOrSubkey > = public_keys_for_encryption
172
+ let pkeys: Vec < & SignedPublicSubKey > = public_keys_for_encryption
276
173
. iter ( )
277
174
. filter_map ( select_pk_for_encryption)
278
175
. collect ( ) ;
279
- let pkeys_refs: Vec < & SignedPublicKeyOrSubkey > = pkeys. iter ( ) . collect ( ) ;
280
176
281
177
let mut rng = thread_rng ( ) ;
282
178
@@ -287,13 +183,9 @@ pub async fn pk_encrypt(
287
183
} else {
288
184
signed_msg
289
185
} ;
290
- compressed_msg. encrypt_to_keys_seipdv1 (
291
- & mut rng,
292
- SYMMETRIC_KEY_ALGORITHM ,
293
- & pkeys_refs,
294
- ) ?
186
+ compressed_msg. encrypt_to_keys_seipdv1 ( & mut rng, SYMMETRIC_KEY_ALGORITHM , & pkeys) ?
295
187
} else {
296
- lit_msg. encrypt_to_keys_seipdv1 ( & mut rng, SYMMETRIC_KEY_ALGORITHM , & pkeys_refs ) ?
188
+ lit_msg. encrypt_to_keys_seipdv1 ( & mut rng, SYMMETRIC_KEY_ALGORITHM , & pkeys ) ?
297
189
} ;
298
190
299
191
let encoded_msg = encrypted_msg. to_armored_string ( Default :: default ( ) ) ?;
0 commit comments