@@ -167,7 +167,10 @@ newtype SignaturesVerified a = SignaturesVerified { signaturesVerified :: a }
167
167
-- | Errors thrown during role validation
168
168
data VerificationError =
169
169
-- | Not enough signatures signed with the appropriate keys
170
- VerificationErrorSignatures TargetPath
170
+ VerificationErrorSignatures TargetPath -- what were we verifying?
171
+ Integer -- threshold
172
+ [KeyId ] -- trusted keys
173
+ [KeyId ] -- found signing keys
171
174
172
175
-- | The file is expired
173
176
| VerificationErrorExpired TargetPath
@@ -218,9 +221,16 @@ instance Show RootUpdated where show = pretty
218
221
instance Exception RootUpdated
219
222
#endif
220
223
224
+ indentedLines :: [String ] -> String
225
+ indentedLines = unlines . map (" " ++ )
226
+
221
227
instance Pretty VerificationError where
222
- pretty (VerificationErrorSignatures file) =
223
- pretty file ++ " does not have enough signatures signed with the appropriate keys"
228
+ pretty (VerificationErrorSignatures file threshold trusted sigs) =
229
+ pretty file ++ " does not have enough signatures signed with the appropriate keys\n "
230
+ ++ " Expected at least " ++ show threshold ++ " signatures from:\n "
231
+ ++ indentedLines (map keyIdString trusted)
232
+ ++ " Found signatures from:\n "
233
+ ++ indentedLines (map keyIdString sigs)
224
234
pretty (VerificationErrorExpired file) =
225
235
pretty file ++ " is expired"
226
236
pretty (VerificationErrorVersion file) =
@@ -235,7 +245,7 @@ instance Pretty VerificationError where
235
245
" Could not deserialize " ++ pretty file ++ " : " ++ pretty err
236
246
pretty (VerificationErrorLoop es) =
237
247
" Verification loop. Errors in order:\n "
238
- ++ unlines (map (( " " ++ ) . either pretty pretty) es)
248
+ ++ indentedLines (map (either pretty pretty) es)
239
249
240
250
instance Pretty RootUpdated where
241
251
pretty RootUpdated = " Root information updated"
@@ -291,15 +301,20 @@ verifyRole' (trusted -> RoleSpec{roleSpecThreshold = KeyThreshold threshold, ..}
291
301
-- was invalid we would already have thrown an error constructing Signed.
292
302
-- (Similarly, if two signatures were made by the same key, the FromJSON
293
303
-- instance for Signatures would have thrown an error.)
294
- unless (length (filter isRoleSpecKey sigs) >= fromIntegral threshold) $
295
- throwError $ VerificationErrorSignatures targetPath
304
+ let nSigs = length (filter isRoleSpecKey sigs)
305
+ unless (nSigs >= fromIntegral threshold) $
306
+ throwError $ VerificationErrorSignatures targetPath (fromIntegral threshold) trustedKeys signingKeys
296
307
297
308
-- Everything is A-OK!
298
309
return $ SignaturesVerified signed
299
310
300
311
isRoleSpecKey :: Signature -> Bool
301
312
isRoleSpecKey Signature {.. } = signatureKey `elem` roleSpecKeys
302
313
314
+ trustedKeys , signingKeys :: [KeyId ]
315
+ trustedKeys = map someKeyId roleSpecKeys
316
+ signingKeys = map (someKeyId . signatureKey) sigs
317
+
303
318
-- | Variation on 'verifyRole' that uses key IDs rather than keys
304
319
--
305
320
-- This is used during the bootstrap process.
@@ -314,9 +329,12 @@ verifyFingerprints fingerprints
314
329
(KeyThreshold threshold)
315
330
targetPath
316
331
Signed {signatures = Signatures sigs, .. } =
317
- if length (filter isTrustedKey sigs ) >= fromIntegral threshold
332
+ if length (filter isTrustedKey signingKeys ) >= fromIntegral threshold
318
333
then Right $ SignaturesVerified signed
319
- else Left $ VerificationErrorSignatures targetPath
334
+ else Left $ VerificationErrorSignatures targetPath ( fromIntegral threshold) fingerprints signingKeys
320
335
where
321
- isTrustedKey :: Signature -> Bool
322
- isTrustedKey Signature {.. } = someKeyId signatureKey `elem` fingerprints
336
+ signingKeys :: [KeyId ]
337
+ signingKeys = map (someKeyId . signatureKey) sigs
338
+
339
+ isTrustedKey :: KeyId -> Bool
340
+ isTrustedKey key = key `elem` fingerprints
0 commit comments