Skip to content

trestle.core.commands.verify

trestle.core.commands.verify ¤

Trestle Verify Command.

Attributes¤

logger = logging.getLogger(__name__) module-attribute ¤

Classes¤

VerifyCmd ¤

Bases: CommandBase


              flowchart TD
              trestle.core.commands.verify.VerifyCmd[VerifyCmd]
              trestle.core.commands.command_docs.CommandBase[CommandBase]

                              trestle.core.commands.command_docs.CommandBase --> trestle.core.commands.verify.VerifyCmd
                


              click trestle.core.commands.verify.VerifyCmd href "" "trestle.core.commands.verify.VerifyCmd"
              click trestle.core.commands.command_docs.CommandBase href "" "trestle.core.commands.command_docs.CommandBase"
            

Verify a JSON file against a detached DSSE provenance envelope.

Verification performs two checks. First, it verifies the DSSE signature over the DSSE pre-authentication encoding for the in-toto Statement payload using the provided PEM public key. Second, it canonicalizes the input JSON using RFC 8785, computes its digest with the signed algorithm, and confirms that the digest matches the subject digest recorded in the signed Statement.

Both checks are required: the digest proves the file matches the signed subject, and the DSSE signature proves the Statement was signed by the corresponding private key. If the envelope was signed with a custom subject name, pass that same value with --subject-name.

Source code in trestle/core/commands/verify.py
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
class VerifyCmd(CommandBase):
    """Verify a JSON file against a detached DSSE provenance envelope.

    Verification performs two checks. First, it verifies the DSSE signature
    over the DSSE pre-authentication encoding for the in-toto Statement payload
    using the provided PEM public key. Second, it canonicalizes the input JSON
    using RFC 8785, computes its digest with the signed algorithm, and confirms that the
    digest matches the subject digest recorded in the signed Statement.

    Both checks are required: the digest proves the file matches the signed
    subject, and the DSSE signature proves the Statement was signed by the
    corresponding private key. If the envelope was signed with a custom subject
    name, pass that same value with --subject-name.
    """

    name = 'verify'

    def _init_arguments(self) -> None:
        self.add_argument('-f', '--file', help='Path to the JSON file to verify.', required=True, type=pathlib.Path)
        self.add_argument('--signature', help='Path to the detached DSSE envelope.', required=True, type=pathlib.Path)
        self.add_argument(
            '--public-key', help='Path to the PEM public key for verification.', required=True, type=pathlib.Path
        )
        self.add_argument(
            '--digest-algorithm',
            choices=[algorithm.value for algorithm in Algorithm],
            help='Require this artifact digest algorithm. By default, detect it from the signed Statement.',
        )
        self.add_argument(
            '--subject-name',
            help='Subject name expected in the in-toto Statement. Defaults to the input file name.',
            default=None,
        )

    @beta_feature('json-signing')
    def _run(self, args: argparse.Namespace) -> int:
        """Verify a JSON file."""
        try:
            log.set_log_level_from_args(args)
            self.verify(
                args.file,
                args.signature,
                args.public_key,
                args.subject_name,
                digest_algorithm=Algorithm(args.digest_algorithm) if args.digest_algorithm else None,
            )
            return CmdReturnCodes.SUCCESS.value
        except Exception as e:  # pragma: no cover
            return handle_generic_command_exception(e, logger, 'Error while verifying JSON signature')

    @classmethod
    def verify(
        cls,
        input_path: pathlib.Path,
        signature_path: pathlib.Path,
        public_key_path: pathlib.Path,
        subject_name: Optional[str] = None,
        digest_algorithm: Optional[Algorithm] = None,
    ) -> None:
        """Verify a detached DSSE provenance envelope for a JSON file."""
        public_key = load_pem_public_key(public_key_path.resolve())
        envelope = load_dsse_envelope(signature_path.resolve())
        verify_oscal_provenance_envelope(input_path.resolve(), envelope, public_key, subject_name, digest_algorithm)
Attributes¤
name = 'verify' class-attribute instance-attribute ¤
Methods:¤
verify(input_path, signature_path, public_key_path, subject_name=None, digest_algorithm=None) classmethod ¤

Verify a detached DSSE provenance envelope for a JSON file.

Source code in trestle/core/commands/verify.py
84
85
86
87
88
89
90
91
92
93
94
95
96
@classmethod
def verify(
    cls,
    input_path: pathlib.Path,
    signature_path: pathlib.Path,
    public_key_path: pathlib.Path,
    subject_name: Optional[str] = None,
    digest_algorithm: Optional[Algorithm] = None,
) -> None:
    """Verify a detached DSSE provenance envelope for a JSON file."""
    public_key = load_pem_public_key(public_key_path.resolve())
    envelope = load_dsse_envelope(signature_path.resolve())
    verify_oscal_provenance_envelope(input_path.resolve(), envelope, public_key, subject_name, digest_algorithm)

Functions:¤

handler: python