@@ -98,27 +98,62 @@ func shouldPreferIdentity(existingId, potentialNewId *packet.Signature) bool {
98
98
// EncryptionKey returns the best candidate Key for encrypting a message to the
99
99
// given Entity.
100
100
func (e * Entity ) EncryptionKey (now time.Time , config * packet.Config ) (Key , bool ) {
101
+ encryptionKey , err := e .EncryptionKeyWithError (now , config )
102
+ return encryptionKey , err == nil
103
+ }
104
+
105
+ // EncryptionKeyWithError returns the best candidate Key for encrypting a message to the
106
+ // given Entity.
107
+ // Provides an error if the function fails to find an encryption key.
108
+ func (e * Entity ) EncryptionKeyWithError (now time.Time , config * packet.Config ) (Key , error ) {
101
109
// The primary key has to be valid at time now
102
110
primarySelfSignature , err := e .VerifyPrimaryKey (now , config )
103
111
if err != nil { // primary key is not valid
104
- return Key {}, false
112
+ return Key {}, errors.ErrEncryptionKeySelection {
113
+ PrimaryKeyId : e .PrimaryKey .KeyIdString (),
114
+ PrimaryKeyErr : err ,
115
+ }
105
116
}
106
117
107
- if checkKeyRequirements (e .PrimaryKey , config ) != nil {
118
+ if err := checkKeyRequirements (e .PrimaryKey , config ); err != nil {
108
119
// The primary key produces weak signatures
109
- return Key {}, false
120
+ return Key {}, errors.ErrEncryptionKeySelection {
121
+ PrimaryKeyId : e .PrimaryKey .KeyIdString (),
122
+ PrimaryKeyErr : err ,
123
+ }
110
124
}
111
125
112
126
// Iterate the keys to find the newest, unexpired one
127
+ var latestSelectionError * errors.ErrEncryptionKeySelection
113
128
candidateSubkey := - 1
114
129
var maxTime time.Time
115
130
var selectedSubkeySelfSig * packet.Signature
116
131
for i , subkey := range e .Subkeys {
132
+ subkeyErr := func (encSelectionErr error ) * errors.ErrEncryptionKeySelection {
133
+ subkeyKeyId := subkey .PublicKey .KeyIdString ()
134
+ return & errors.ErrEncryptionKeySelection {
135
+ PrimaryKeyId : e .PrimaryKey .KeyIdString (),
136
+ EncSelectionKeyId : & subkeyKeyId ,
137
+ EncSelectionErr : encSelectionErr ,
138
+ }
139
+
140
+ }
141
+ // Verify the subkey signature.
117
142
subkeySelfSig , err := subkey .Verify (now , config ) // subkey has to be valid at time now
118
- if err == nil &&
119
- isValidEncryptionKey (subkeySelfSig , subkey .PublicKey .PubKeyAlgo , config ) &&
120
- checkKeyRequirements (subkey .PublicKey , config ) == nil &&
121
- (maxTime .IsZero () || subkeySelfSig .CreationTime .Unix () >= maxTime .Unix ()) {
143
+ if err != nil {
144
+ latestSelectionError = subkeyErr (err )
145
+ continue
146
+ }
147
+ // Check the algorithm and key flags.
148
+ if ! isValidEncryptionKey (subkeySelfSig , subkey .PublicKey .PubKeyAlgo , config ) {
149
+ continue
150
+ }
151
+ // Check if the key fulfils the requirements
152
+ if err := checkKeyRequirements (subkey .PublicKey , config ); err != nil {
153
+ latestSelectionError = subkeyErr (err )
154
+ continue
155
+ }
156
+ if maxTime .IsZero () || subkeySelfSig .CreationTime .Unix () >= maxTime .Unix () {
122
157
candidateSubkey = i
123
158
selectedSubkeySelfSig = subkeySelfSig
124
159
maxTime = subkeySelfSig .CreationTime
@@ -133,7 +168,7 @@ func (e *Entity) EncryptionKey(now time.Time, config *packet.Config) (Key, bool)
133
168
PublicKey : subkey .PublicKey ,
134
169
PrivateKey : subkey .PrivateKey ,
135
170
SelfSignature : selectedSubkeySelfSig ,
136
- }, true
171
+ }, nil
137
172
}
138
173
139
174
// If we don't have any subkeys for encryption and the primary key
@@ -145,10 +180,17 @@ func (e *Entity) EncryptionKey(now time.Time, config *packet.Config) (Key, bool)
145
180
PublicKey : e .PrimaryKey ,
146
181
PrivateKey : e .PrivateKey ,
147
182
SelfSignature : primarySelfSignature ,
148
- }, true
183
+ }, nil
184
+ }
185
+
186
+ if latestSelectionError == nil {
187
+ latestSelectionError = & errors.ErrEncryptionKeySelection {
188
+ PrimaryKeyId : e .PrimaryKey .KeyIdString (),
189
+ EncSelectionErr : goerrors .New ("no encryption-capable key found (no key flags or invalid algorithm)" ),
190
+ }
149
191
}
150
192
151
- return Key {}, false
193
+ return Key {}, latestSelectionError
152
194
}
153
195
154
196
// DecryptionKeys returns all keys that are available for decryption, matching the keyID when given
0 commit comments