pyhanko-cli 0.4.2__tar.gz → 0.5.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (324) hide show
  1. {pyhanko_cli-0.4.2/src/pyhanko_cli.egg-info → pyhanko_cli-0.5.0}/PKG-INFO +3 -3
  2. pyhanko_cli-0.5.0/pyhanko_testing_commons/docs_testing.py +647 -0
  3. {pyhanko_cli-0.4.2 → pyhanko_cli-0.5.0}/pyhanko_testing_commons/test_data/data/crypto/certomancer.yml +7 -0
  4. pyhanko_cli-0.5.0/pyhanko_testing_commons/test_utils/live_http.py +210 -0
  5. pyhanko_cli-0.5.0/pyhanko_testing_commons/test_utils/live_http_fixtures.py +22 -0
  6. {pyhanko_cli-0.4.2 → pyhanko_cli-0.5.0}/pyhanko_testing_commons/test_utils/signing_commons.py +5 -6
  7. {pyhanko_cli-0.4.2 → pyhanko_cli-0.5.0}/pyproject.toml +4 -4
  8. {pyhanko_cli-0.4.2 → pyhanko_cli-0.5.0}/src/pyhanko/cli/_root.py +2 -2
  9. {pyhanko_cli-0.4.2 → pyhanko_cli-0.5.0}/src/pyhanko/cli/_trust.py +38 -34
  10. {pyhanko_cli-0.4.2 → pyhanko_cli-0.5.0}/src/pyhanko/cli/commands/signing/plugin.py +2 -1
  11. {pyhanko_cli-0.4.2 → pyhanko_cli-0.5.0}/src/pyhanko/cli/config.py +3 -1
  12. pyhanko_cli-0.5.0/src/pyhanko/cli/version.py +2 -0
  13. {pyhanko_cli-0.4.2 → pyhanko_cli-0.5.0/src/pyhanko_cli.egg-info}/PKG-INFO +3 -3
  14. {pyhanko_cli-0.4.2 → pyhanko_cli-0.5.0}/src/pyhanko_cli.egg-info/SOURCES.txt +3 -0
  15. {pyhanko_cli-0.4.2 → pyhanko_cli-0.5.0}/src/pyhanko_cli.egg-info/requires.txt +2 -2
  16. {pyhanko_cli-0.4.2 → pyhanko_cli-0.5.0}/tests/conftest.py +4 -5
  17. {pyhanko_cli-0.4.2 → pyhanko_cli-0.5.0}/tests/test_cli_crypt.py +1 -1
  18. {pyhanko_cli-0.4.2 → pyhanko_cli-0.5.0}/tests/test_cli_ltv.py +3 -0
  19. {pyhanko_cli-0.4.2 → pyhanko_cli-0.5.0}/tests/test_cli_signing.py +9 -3
  20. {pyhanko_cli-0.4.2 → pyhanko_cli-0.5.0}/tests/test_config.py +56 -2
  21. {pyhanko_cli-0.4.2 → pyhanko_cli-0.5.0}/tests/test_runtime.py +7 -2
  22. {pyhanko_cli-0.4.2 → pyhanko_cli-0.5.0}/tests/validation/test_cli_qualified_validation.py +31 -1
  23. {pyhanko_cli-0.4.2 → pyhanko_cli-0.5.0}/tests/validation/test_cli_validation.py +120 -10
  24. pyhanko_cli-0.4.2/src/pyhanko/cli/version.py +0 -2
  25. {pyhanko_cli-0.4.2 → pyhanko_cli-0.5.0}/LICENSE +0 -0
  26. {pyhanko_cli-0.4.2 → pyhanko_cli-0.5.0}/MANIFEST.in +0 -0
  27. {pyhanko_cli-0.4.2 → pyhanko_cli-0.5.0}/README.md +0 -0
  28. {pyhanko_cli-0.4.2 → pyhanko_cli-0.5.0}/pyhanko_testing_commons/__init__.py +0 -0
  29. {pyhanko_cli-0.4.2 → pyhanko_cli-0.5.0}/pyhanko_testing_commons/test_data/__init__.py +0 -0
  30. {pyhanko_cli-0.4.2 → pyhanko_cli-0.5.0}/pyhanko_testing_commons/test_data/certomancer_trust_lists.py +0 -0
  31. {pyhanko_cli-0.4.2 → pyhanko_cli-0.5.0}/pyhanko_testing_commons/test_data/data/crypto/keys-dsa/intermediate_ca.key.pem +0 -0
  32. {pyhanko_cli-0.4.2 → pyhanko_cli-0.5.0}/pyhanko_testing_commons/test_data/data/crypto/keys-dsa/ocsp.key.pem +0 -0
  33. {pyhanko_cli-0.4.2 → pyhanko_cli-0.5.0}/pyhanko_testing_commons/test_data/data/crypto/keys-dsa/params.pem +0 -0
  34. {pyhanko_cli-0.4.2 → pyhanko_cli-0.5.0}/pyhanko_testing_commons/test_data/data/crypto/keys-dsa/root_ca.key.pem +0 -0
  35. {pyhanko_cli-0.4.2 → pyhanko_cli-0.5.0}/pyhanko_testing_commons/test_data/data/crypto/keys-dsa/signer.key.pem +0 -0
  36. {pyhanko_cli-0.4.2 → pyhanko_cli-0.5.0}/pyhanko_testing_commons/test_data/data/crypto/keys-dsa/signer2.key.pem +0 -0
  37. {pyhanko_cli-0.4.2 → pyhanko_cli-0.5.0}/pyhanko_testing_commons/test_data/data/crypto/keys-dsa/tsa.key.pem +0 -0
  38. {pyhanko_cli-0.4.2 → pyhanko_cli-0.5.0}/pyhanko_testing_commons/test_data/data/crypto/keys-dsa/tsa2.key.pem +0 -0
  39. {pyhanko_cli-0.4.2 → pyhanko_cli-0.5.0}/pyhanko_testing_commons/test_data/data/crypto/keys-ecdsa/decrypter-x25519.key.pem +0 -0
  40. {pyhanko_cli-0.4.2 → pyhanko_cli-0.5.0}/pyhanko_testing_commons/test_data/data/crypto/keys-ecdsa/decrypter-x448.key.pem +0 -0
  41. {pyhanko_cli-0.4.2 → pyhanko_cli-0.5.0}/pyhanko_testing_commons/test_data/data/crypto/keys-ecdsa/decrypter1.key.pem +0 -0
  42. {pyhanko_cli-0.4.2 → pyhanko_cli-0.5.0}/pyhanko_testing_commons/test_data/data/crypto/keys-ecdsa/decrypter2.key.pem +0 -0
  43. {pyhanko_cli-0.4.2 → pyhanko_cli-0.5.0}/pyhanko_testing_commons/test_data/data/crypto/keys-ecdsa/decrypter3.key.pem +0 -0
  44. {pyhanko_cli-0.4.2 → pyhanko_cli-0.5.0}/pyhanko_testing_commons/test_data/data/crypto/keys-ecdsa/intermediate_ca.key.pem +0 -0
  45. {pyhanko_cli-0.4.2 → pyhanko_cli-0.5.0}/pyhanko_testing_commons/test_data/data/crypto/keys-ecdsa/ocsp.key.pem +0 -0
  46. {pyhanko_cli-0.4.2 → pyhanko_cli-0.5.0}/pyhanko_testing_commons/test_data/data/crypto/keys-ecdsa/root_ca.key.pem +0 -0
  47. {pyhanko_cli-0.4.2 → pyhanko_cli-0.5.0}/pyhanko_testing_commons/test_data/data/crypto/keys-ecdsa/signer.key.pem +0 -0
  48. {pyhanko_cli-0.4.2 → pyhanko_cli-0.5.0}/pyhanko_testing_commons/test_data/data/crypto/keys-ecdsa/signer2.key.pem +0 -0
  49. {pyhanko_cli-0.4.2 → pyhanko_cli-0.5.0}/pyhanko_testing_commons/test_data/data/crypto/keys-ecdsa/tsa.key.pem +0 -0
  50. {pyhanko_cli-0.4.2 → pyhanko_cli-0.5.0}/pyhanko_testing_commons/test_data/data/crypto/keys-ecdsa/tsa2.key.pem +0 -0
  51. {pyhanko_cli-0.4.2 → pyhanko_cli-0.5.0}/pyhanko_testing_commons/test_data/data/crypto/keys-ecdsa/tsa_rsa.key.pem +0 -0
  52. {pyhanko_cli-0.4.2 → pyhanko_cli-0.5.0}/pyhanko_testing_commons/test_data/data/crypto/keys-ed25519/intermediate_ca.key.pem +0 -0
  53. {pyhanko_cli-0.4.2 → pyhanko_cli-0.5.0}/pyhanko_testing_commons/test_data/data/crypto/keys-ed25519/ocsp.key.pem +0 -0
  54. {pyhanko_cli-0.4.2 → pyhanko_cli-0.5.0}/pyhanko_testing_commons/test_data/data/crypto/keys-ed25519/root_ca.key.pem +0 -0
  55. {pyhanko_cli-0.4.2 → pyhanko_cli-0.5.0}/pyhanko_testing_commons/test_data/data/crypto/keys-ed25519/signer.key.pem +0 -0
  56. {pyhanko_cli-0.4.2 → pyhanko_cli-0.5.0}/pyhanko_testing_commons/test_data/data/crypto/keys-ed25519/signer2.key.pem +0 -0
  57. {pyhanko_cli-0.4.2 → pyhanko_cli-0.5.0}/pyhanko_testing_commons/test_data/data/crypto/keys-ed25519/tsa.key.pem +0 -0
  58. {pyhanko_cli-0.4.2 → pyhanko_cli-0.5.0}/pyhanko_testing_commons/test_data/data/crypto/keys-ed25519/tsa2.key.pem +0 -0
  59. {pyhanko_cli-0.4.2 → pyhanko_cli-0.5.0}/pyhanko_testing_commons/test_data/data/crypto/keys-ed448/intermediate_ca.key.pem +0 -0
  60. {pyhanko_cli-0.4.2 → pyhanko_cli-0.5.0}/pyhanko_testing_commons/test_data/data/crypto/keys-ed448/ocsp.key.pem +0 -0
  61. {pyhanko_cli-0.4.2 → pyhanko_cli-0.5.0}/pyhanko_testing_commons/test_data/data/crypto/keys-ed448/root_ca.key.pem +0 -0
  62. {pyhanko_cli-0.4.2 → pyhanko_cli-0.5.0}/pyhanko_testing_commons/test_data/data/crypto/keys-ed448/signer.key.pem +0 -0
  63. {pyhanko_cli-0.4.2 → pyhanko_cli-0.5.0}/pyhanko_testing_commons/test_data/data/crypto/keys-ed448/signer2.key.pem +0 -0
  64. {pyhanko_cli-0.4.2 → pyhanko_cli-0.5.0}/pyhanko_testing_commons/test_data/data/crypto/keys-ed448/tsa.key.pem +0 -0
  65. {pyhanko_cli-0.4.2 → pyhanko_cli-0.5.0}/pyhanko_testing_commons/test_data/data/crypto/keys-ed448/tsa2.key.pem +0 -0
  66. {pyhanko_cli-0.4.2 → pyhanko_cli-0.5.0}/pyhanko_testing_commons/test_data/data/crypto/keys-mldsa/intermediate_ca.key.pem +0 -0
  67. {pyhanko_cli-0.4.2 → pyhanko_cli-0.5.0}/pyhanko_testing_commons/test_data/data/crypto/keys-mldsa/ocsp.key.pem +0 -0
  68. {pyhanko_cli-0.4.2 → pyhanko_cli-0.5.0}/pyhanko_testing_commons/test_data/data/crypto/keys-mldsa/root_ca.key.pem +0 -0
  69. {pyhanko_cli-0.4.2 → pyhanko_cli-0.5.0}/pyhanko_testing_commons/test_data/data/crypto/keys-mldsa/signer_mldsa44.key.pem +0 -0
  70. {pyhanko_cli-0.4.2 → pyhanko_cli-0.5.0}/pyhanko_testing_commons/test_data/data/crypto/keys-mldsa/signer_mldsa65.key.pem +0 -0
  71. {pyhanko_cli-0.4.2 → pyhanko_cli-0.5.0}/pyhanko_testing_commons/test_data/data/crypto/keys-mldsa/signer_mldsa87.key.pem +0 -0
  72. {pyhanko_cli-0.4.2 → pyhanko_cli-0.5.0}/pyhanko_testing_commons/test_data/data/crypto/keys-mldsa/tsa.key.pem +0 -0
  73. {pyhanko_cli-0.4.2 → pyhanko_cli-0.5.0}/pyhanko_testing_commons/test_data/data/crypto/keys-mldsa/tsa2.key.pem +0 -0
  74. {pyhanko_cli-0.4.2 → pyhanko_cli-0.5.0}/pyhanko_testing_commons/test_data/data/crypto/keys-rsa/indep_tsa.key.pem +0 -0
  75. {pyhanko_cli-0.4.2 → pyhanko_cli-0.5.0}/pyhanko_testing_commons/test_data/data/crypto/keys-rsa/indep_tsa_root.key.pem +0 -0
  76. {pyhanko_cli-0.4.2 → pyhanko_cli-0.5.0}/pyhanko_testing_commons/test_data/data/crypto/keys-rsa/interm_aa.key.pem +0 -0
  77. {pyhanko_cli-0.4.2 → pyhanko_cli-0.5.0}/pyhanko_testing_commons/test_data/data/crypto/keys-rsa/intermediate_ca.key.pem +0 -0
  78. {pyhanko_cli-0.4.2 → pyhanko_cli-0.5.0}/pyhanko_testing_commons/test_data/data/crypto/keys-rsa/leaf_aa.key.pem +0 -0
  79. {pyhanko_cli-0.4.2 → pyhanko_cli-0.5.0}/pyhanko_testing_commons/test_data/data/crypto/keys-rsa/ocsp.key.pem +0 -0
  80. {pyhanko_cli-0.4.2 → pyhanko_cli-0.5.0}/pyhanko_testing_commons/test_data/data/crypto/keys-rsa/root_aa.key.pem +0 -0
  81. {pyhanko_cli-0.4.2 → pyhanko_cli-0.5.0}/pyhanko_testing_commons/test_data/data/crypto/keys-rsa/root_ca.key.pem +0 -0
  82. {pyhanko_cli-0.4.2 → pyhanko_cli-0.5.0}/pyhanko_testing_commons/test_data/data/crypto/keys-rsa/signer.key.pem +0 -0
  83. {pyhanko_cli-0.4.2 → pyhanko_cli-0.5.0}/pyhanko_testing_commons/test_data/data/crypto/keys-rsa/signer2.key.pem +0 -0
  84. {pyhanko_cli-0.4.2 → pyhanko_cli-0.5.0}/pyhanko_testing_commons/test_data/data/crypto/keys-rsa/tsa.key.pem +0 -0
  85. {pyhanko_cli-0.4.2 → pyhanko_cli-0.5.0}/pyhanko_testing_commons/test_data/data/crypto/keys-rsa/tsa2.key.pem +0 -0
  86. {pyhanko_cli-0.4.2 → pyhanko_cli-0.5.0}/pyhanko_testing_commons/test_data/data/crypto/ocsp.req.der +0 -0
  87. {pyhanko_cli-0.4.2 → pyhanko_cli-0.5.0}/pyhanko_testing_commons/test_data/data/crypto/ocsp.resp.der +0 -0
  88. {pyhanko_cli-0.4.2 → pyhanko_cli-0.5.0}/pyhanko_testing_commons/test_data/data/crypto/real-misissued-qtst-cert.cer +0 -0
  89. {pyhanko_cli-0.4.2 → pyhanko_cli-0.5.0}/pyhanko_testing_commons/test_data/data/crypto/real-qcert.cer +0 -0
  90. {pyhanko_cli-0.4.2 → pyhanko_cli-0.5.0}/pyhanko_testing_commons/test_data/data/crypto/real-qtst-cert.cer +0 -0
  91. {pyhanko_cli-0.4.2 → pyhanko_cli-0.5.0}/pyhanko_testing_commons/test_data/data/crypto/selfsigned.cert.pem +0 -0
  92. {pyhanko_cli-0.4.2 → pyhanko_cli-0.5.0}/pyhanko_testing_commons/test_data/data/crypto/selfsigned.key.pem +0 -0
  93. {pyhanko_cli-0.4.2 → pyhanko_cli-0.5.0}/pyhanko_testing_commons/test_data/data/crypto/selfsigned.pfx +0 -0
  94. {pyhanko_cli-0.4.2 → pyhanko_cli-0.5.0}/pyhanko_testing_commons/test_data/data/crypto/some-chain.cert.pem +0 -0
  95. {pyhanko_cli-0.4.2 → pyhanko_cli-0.5.0}/pyhanko_testing_commons/test_data/data/crypto/testing-ca/ca-chain.cert.pem +0 -0
  96. {pyhanko_cli-0.4.2 → pyhanko_cli-0.5.0}/pyhanko_testing_commons/test_data/data/crypto/testing-ca/interm/decrypter1-old.cert.pem +0 -0
  97. {pyhanko_cli-0.4.2 → pyhanko_cli-0.5.0}/pyhanko_testing_commons/test_data/data/crypto/testing-ca/interm/decrypter1.cert.pem +0 -0
  98. {pyhanko_cli-0.4.2 → pyhanko_cli-0.5.0}/pyhanko_testing_commons/test_data/data/crypto/testing-ca/interm/decrypter1.pfx +0 -0
  99. {pyhanko_cli-0.4.2 → pyhanko_cli-0.5.0}/pyhanko_testing_commons/test_data/data/crypto/testing-ca/interm/decrypter2.cert.pem +0 -0
  100. {pyhanko_cli-0.4.2 → pyhanko_cli-0.5.0}/pyhanko_testing_commons/test_data/data/crypto/testing-ca/interm/decrypter2.pfx +0 -0
  101. {pyhanko_cli-0.4.2 → pyhanko_cli-0.5.0}/pyhanko_testing_commons/test_data/data/crypto/testing-ca/interm/interm-ocsp.cert.pem +0 -0
  102. {pyhanko_cli-0.4.2 → pyhanko_cli-0.5.0}/pyhanko_testing_commons/test_data/data/crypto/testing-ca/interm/interm-ocsp.pfx +0 -0
  103. {pyhanko_cli-0.4.2 → pyhanko_cli-0.5.0}/pyhanko_testing_commons/test_data/data/crypto/testing-ca/interm/signer1-long.cert.pem +0 -0
  104. {pyhanko_cli-0.4.2 → pyhanko_cli-0.5.0}/pyhanko_testing_commons/test_data/data/crypto/testing-ca/interm/signer1-long.pfx +0 -0
  105. {pyhanko_cli-0.4.2 → pyhanko_cli-0.5.0}/pyhanko_testing_commons/test_data/data/crypto/testing-ca/interm/signer1.cert.pem +0 -0
  106. {pyhanko_cli-0.4.2 → pyhanko_cli-0.5.0}/pyhanko_testing_commons/test_data/data/crypto/testing-ca/interm/signer1.pfx +0 -0
  107. {pyhanko_cli-0.4.2 → pyhanko_cli-0.5.0}/pyhanko_testing_commons/test_data/data/crypto/testing-ca/interm/signer2.cert.pem +0 -0
  108. {pyhanko_cli-0.4.2 → pyhanko_cli-0.5.0}/pyhanko_testing_commons/test_data/data/crypto/testing-ca/interm/signer2.pfx +0 -0
  109. {pyhanko_cli-0.4.2 → pyhanko_cli-0.5.0}/pyhanko_testing_commons/test_data/data/crypto/testing-ca/root/interm.cert.pem +0 -0
  110. {pyhanko_cli-0.4.2 → pyhanko_cli-0.5.0}/pyhanko_testing_commons/test_data/data/crypto/testing-ca/root/interm.pfx +0 -0
  111. {pyhanko_cli-0.4.2 → pyhanko_cli-0.5.0}/pyhanko_testing_commons/test_data/data/crypto/testing-ca/root/root.cert.pem +0 -0
  112. {pyhanko_cli-0.4.2 → pyhanko_cli-0.5.0}/pyhanko_testing_commons/test_data/data/crypto/testing-ca/root/root.pfx +0 -0
  113. {pyhanko_cli-0.4.2 → pyhanko_cli-0.5.0}/pyhanko_testing_commons/test_data/data/crypto/testing-ca/root/tsa.cert.pem +0 -0
  114. {pyhanko_cli-0.4.2 → pyhanko_cli-0.5.0}/pyhanko_testing_commons/test_data/data/crypto/testing-ca/root/tsa.pfx +0 -0
  115. {pyhanko_cli-0.4.2 → pyhanko_cli-0.5.0}/pyhanko_testing_commons/test_data/data/crypto/testing-ca/root/tsa2.cert.pem +0 -0
  116. {pyhanko_cli-0.4.2 → pyhanko_cli-0.5.0}/pyhanko_testing_commons/test_data/data/crypto/testing-ca/root/tsa2.pfx +0 -0
  117. {pyhanko_cli-0.4.2 → pyhanko_cli-0.5.0}/pyhanko_testing_commons/test_data/data/crypto/testing-ca-setup/ca-setup.sh +0 -0
  118. {pyhanko_cli-0.4.2 → pyhanko_cli-0.5.0}/pyhanko_testing_commons/test_data/data/crypto/testing-ca-setup/openssl.base.cnf +0 -0
  119. {pyhanko_cli-0.4.2 → pyhanko_cli-0.5.0}/pyhanko_testing_commons/test_data/data/crypto/testing-ca-setup/pkcs11-setup-certomancer.sh +0 -0
  120. {pyhanko_cli-0.4.2 → pyhanko_cli-0.5.0}/pyhanko_testing_commons/test_data/data/crypto/testing-ca-setup/pkcs11-setup.sh +0 -0
  121. {pyhanko_cli-0.4.2 → pyhanko_cli-0.5.0}/pyhanko_testing_commons/test_data/data/crypto/testing-ca-setup/setup-params +0 -0
  122. {pyhanko_cli-0.4.2 → pyhanko_cli-0.5.0}/pyhanko_testing_commons/test_data/data/crypto/tsa.cert.pem +0 -0
  123. {pyhanko_cli-0.4.2 → pyhanko_cli-0.5.0}/pyhanko_testing_commons/test_data/data/fonts/LICENSE.Noto +0 -0
  124. {pyhanko_cli-0.4.2 → pyhanko_cli-0.5.0}/pyhanko_testing_commons/test_data/data/fonts/LICENSE.SourceSerif +0 -0
  125. {pyhanko_cli-0.4.2 → pyhanko_cli-0.5.0}/pyhanko_testing_commons/test_data/data/fonts/NotoSans-Regular.ttf +0 -0
  126. {pyhanko_cli-0.4.2 → pyhanko_cli-0.5.0}/pyhanko_testing_commons/test_data/data/fonts/NotoSansArabic-Regular.ttf +0 -0
  127. {pyhanko_cli-0.4.2 → pyhanko_cli-0.5.0}/pyhanko_testing_commons/test_data/data/fonts/NotoSerifJP-Regular.otf +0 -0
  128. {pyhanko_cli-0.4.2 → pyhanko_cli-0.5.0}/pyhanko_testing_commons/test_data/data/fonts/NotoSerifSubset.otf +0 -0
  129. {pyhanko_cli-0.4.2 → pyhanko_cli-0.5.0}/pyhanko_testing_commons/test_data/data/fonts/SourceSerif4-Regular.otf +0 -0
  130. {pyhanko_cli-0.4.2 → pyhanko_cli-0.5.0}/pyhanko_testing_commons/test_data/data/img/stamp-indexed.png +0 -0
  131. {pyhanko_cli-0.4.2 → pyhanko_cli-0.5.0}/pyhanko_testing_commons/test_data/data/img/stamp.png +0 -0
  132. {pyhanko_cli-0.4.2 → pyhanko_cli-0.5.0}/pyhanko_testing_commons/test_data/data/pdf/.gitignore +0 -0
  133. {pyhanko_cli-0.4.2 → pyhanko_cli-0.5.0}/pyhanko_testing_commons/test_data/data/pdf/broken-objstream1.pdf +0 -0
  134. {pyhanko_cli-0.4.2 → pyhanko_cli-0.5.0}/pyhanko_testing_commons/test_data/data/pdf/broken-objstream2.pdf +0 -0
  135. {pyhanko_cli-0.4.2 → pyhanko_cli-0.5.0}/pyhanko_testing_commons/test_data/data/pdf/broken-objstream3.pdf +0 -0
  136. {pyhanko_cli-0.4.2 → pyhanko_cli-0.5.0}/pyhanko_testing_commons/test_data/data/pdf/broken-objstream4.pdf +0 -0
  137. {pyhanko_cli-0.4.2 → pyhanko_cli-0.5.0}/pyhanko_testing_commons/test_data/data/pdf/broken-objstream5.pdf +0 -0
  138. {pyhanko_cli-0.4.2 → pyhanko_cli-0.5.0}/pyhanko_testing_commons/test_data/data/pdf/broken-objstream6.pdf +0 -0
  139. {pyhanko_cli-0.4.2 → pyhanko_cli-0.5.0}/pyhanko_testing_commons/test_data/data/pdf/certified-with-indirect-refs-in-dir.pdf +0 -0
  140. {pyhanko_cli-0.4.2 → pyhanko_cli-0.5.0}/pyhanko_testing_commons/test_data/data/pdf/circular-page-tree.pdf +0 -0
  141. {pyhanko_cli-0.4.2 → pyhanko_cli-0.5.0}/pyhanko_testing_commons/test_data/data/pdf/coverage-anomalies/base.pdf +0 -0
  142. {pyhanko_cli-0.4.2 → pyhanko_cli-0.5.0}/pyhanko_testing_commons/test_data/data/pdf/coverage-anomalies/one-byterange.pdf +0 -0
  143. {pyhanko_cli-0.4.2 → pyhanko_cli-0.5.0}/pyhanko_testing_commons/test_data/data/pdf/coverage-anomalies/signature-gap-too-big.pdf +0 -0
  144. {pyhanko_cli-0.4.2 → pyhanko_cli-0.5.0}/pyhanko_testing_commons/test_data/data/pdf/coverage-anomalies/tail-uncovered.pdf +0 -0
  145. {pyhanko_cli-0.4.2 → pyhanko_cli-0.5.0}/pyhanko_testing_commons/test_data/data/pdf/coverage-anomalies/weird-byterange.pdf +0 -0
  146. {pyhanko_cli-0.4.2 → pyhanko_cli-0.5.0}/pyhanko_testing_commons/test_data/data/pdf/ed448-disallowed-hash.pdf +0 -0
  147. {pyhanko_cli-0.4.2 → pyhanko_cli-0.5.0}/pyhanko_testing_commons/test_data/data/pdf/ed448-shake256-nolen.pdf +0 -0
  148. {pyhanko_cli-0.4.2 → pyhanko_cli-0.5.0}/pyhanko_testing_commons/test_data/data/pdf/embedded-encrypted-nocf.pdf +0 -0
  149. {pyhanko_cli-0.4.2 → pyhanko_cli-0.5.0}/pyhanko_testing_commons/test_data/data/pdf/empty-a4.pdf +0 -0
  150. {pyhanko_cli-0.4.2 → pyhanko_cli-0.5.0}/pyhanko_testing_commons/test_data/data/pdf/extensions-direct.pdf +0 -0
  151. {pyhanko_cli-0.4.2 → pyhanko_cli-0.5.0}/pyhanko_testing_commons/test_data/data/pdf/extensions-indirect-not-all-paths.pdf +0 -0
  152. {pyhanko_cli-0.4.2 → pyhanko_cli-0.5.0}/pyhanko_testing_commons/test_data/data/pdf/extensions-indirect.pdf +0 -0
  153. {pyhanko_cli-0.4.2 → pyhanko_cli-0.5.0}/pyhanko_testing_commons/test_data/data/pdf/extensions-update-direct.pdf +0 -0
  154. {pyhanko_cli-0.4.2 → pyhanko_cli-0.5.0}/pyhanko_testing_commons/test_data/data/pdf/extensions-update-indirect.pdf +0 -0
  155. {pyhanko_cli-0.4.2 → pyhanko_cli-0.5.0}/pyhanko_testing_commons/test_data/data/pdf/fontembed.pdf +0 -0
  156. {pyhanko_cli-0.4.2 → pyhanko_cli-0.5.0}/pyhanko_testing_commons/test_data/data/pdf/form-tree-circular-ref-input.pdf +0 -0
  157. {pyhanko_cli-0.4.2 → pyhanko_cli-0.5.0}/pyhanko_testing_commons/test_data/data/pdf/form-update-ap-indirect-sneaky-trailer.pdf +0 -0
  158. {pyhanko_cli-0.4.2 → pyhanko_cli-0.5.0}/pyhanko_testing_commons/test_data/data/pdf/form-update-no-override-appearance-stream-ap-indirect-sneaky.pdf +0 -0
  159. {pyhanko_cli-0.4.2 → pyhanko_cli-0.5.0}/pyhanko_testing_commons/test_data/data/pdf/form-update-no-override-appearance-stream-ap-indirect.pdf +0 -0
  160. {pyhanko_cli-0.4.2 → pyhanko_cli-0.5.0}/pyhanko_testing_commons/test_data/data/pdf/form-update-original-ap-type-wrong.pdf +0 -0
  161. {pyhanko_cli-0.4.2 → pyhanko_cli-0.5.0}/pyhanko_testing_commons/test_data/data/pdf/form-update-override-appearance-stream-ap-indirect-sneaky.pdf +0 -0
  162. {pyhanko_cli-0.4.2 → pyhanko_cli-0.5.0}/pyhanko_testing_commons/test_data/data/pdf/form-update-override-appearance-stream-ap-indirect.pdf +0 -0
  163. {pyhanko_cli-0.4.2 → pyhanko_cli-0.5.0}/pyhanko_testing_commons/test_data/data/pdf/form-update-override-appearance-stream-sneaky.pdf +0 -0
  164. {pyhanko_cli-0.4.2 → pyhanko_cli-0.5.0}/pyhanko_testing_commons/test_data/data/pdf/form-update-override-appearance-stream.pdf +0 -0
  165. {pyhanko_cli-0.4.2 → pyhanko_cli-0.5.0}/pyhanko_testing_commons/test_data/data/pdf/info-bin-producer-string.pdf +0 -0
  166. {pyhanko_cli-0.4.2 → pyhanko_cli-0.5.0}/pyhanko_testing_commons/test_data/data/pdf/layout-tests/arabic-box.pdf +0 -0
  167. {pyhanko_cli-0.4.2 → pyhanko_cli-0.5.0}/pyhanko_testing_commons/test_data/data/pdf/layout-tests/bitmap-bg.pdf +0 -0
  168. {pyhanko_cli-0.4.2 → pyhanko_cli-0.5.0}/pyhanko_testing_commons/test_data/data/pdf/layout-tests/code128-test.pdf +0 -0
  169. {pyhanko_cli-0.4.2 → pyhanko_cli-0.5.0}/pyhanko_testing_commons/test_data/data/pdf/layout-tests/default-font.pdf +0 -0
  170. {pyhanko_cli-0.4.2 → pyhanko_cli-0.5.0}/pyhanko_testing_commons/test_data/data/pdf/layout-tests/double-newline.pdf +0 -0
  171. {pyhanko_cli-0.4.2 → pyhanko_cli-0.5.0}/pyhanko_testing_commons/test_data/data/pdf/layout-tests/fancy-qr-stamp-test.pdf +0 -0
  172. {pyhanko_cli-0.4.2 → pyhanko_cli-0.5.0}/pyhanko_testing_commons/test_data/data/pdf/layout-tests/form-fill-result.pdf +0 -0
  173. {pyhanko_cli-0.4.2 → pyhanko_cli-0.5.0}/pyhanko_testing_commons/test_data/data/pdf/layout-tests/four-stamps-fixed.pdf +0 -0
  174. {pyhanko_cli-0.4.2 → pyhanko_cli-0.5.0}/pyhanko_testing_commons/test_data/data/pdf/layout-tests/four-stamps-natural.pdf +0 -0
  175. {pyhanko_cli-0.4.2 → pyhanko_cli-0.5.0}/pyhanko_testing_commons/test_data/data/pdf/layout-tests/ja-vert-stamps.pdf +0 -0
  176. {pyhanko_cli-0.4.2 → pyhanko_cli-0.5.0}/pyhanko_testing_commons/test_data/data/pdf/layout-tests/leaky-graphics-state-stamp-no-corr-result.pdf +0 -0
  177. {pyhanko_cli-0.4.2 → pyhanko_cli-0.5.0}/pyhanko_testing_commons/test_data/data/pdf/layout-tests/leaky-graphics-state-stamp-result.pdf +0 -0
  178. {pyhanko_cli-0.4.2 → pyhanko_cli-0.5.0}/pyhanko_testing_commons/test_data/data/pdf/layout-tests/multiline-textbox-nondefault-fs.pdf +0 -0
  179. {pyhanko_cli-0.4.2 → pyhanko_cli-0.5.0}/pyhanko_testing_commons/test_data/data/pdf/layout-tests/scaled-bitmap-bg.pdf +0 -0
  180. {pyhanko_cli-0.4.2 → pyhanko_cli-0.5.0}/pyhanko_testing_commons/test_data/data/pdf/layout-tests/source-serif-test.pdf +0 -0
  181. {pyhanko_cli-0.4.2 → pyhanko_cli-0.5.0}/pyhanko_testing_commons/test_data/data/pdf/layout-tests/stamp-from-static-pdf.pdf +0 -0
  182. {pyhanko_cli-0.4.2 → pyhanko_cli-0.5.0}/pyhanko_testing_commons/test_data/data/pdf/layout-tests/stamp-on-pdf-bg.pdf +0 -0
  183. {pyhanko_cli-0.4.2 → pyhanko_cli-0.5.0}/pyhanko_testing_commons/test_data/data/pdf/layout-tests/text-stamp-color.pdf +0 -0
  184. {pyhanko_cli-0.4.2 → pyhanko_cli-0.5.0}/pyhanko_testing_commons/test_data/data/pdf/layout-tests/undef-bg-size.pdf +0 -0
  185. {pyhanko_cli-0.4.2 → pyhanko_cli-0.5.0}/pyhanko_testing_commons/test_data/data/pdf/leaky-graphics-state-doc.pdf +0 -0
  186. {pyhanko_cli-0.4.2 → pyhanko_cli-0.5.0}/pyhanko_testing_commons/test_data/data/pdf/malformed-encrypt-dict1.pdf +0 -0
  187. {pyhanko_cli-0.4.2 → pyhanko_cli-0.5.0}/pyhanko_testing_commons/test_data/data/pdf/malformed-encrypt-dict2.pdf +0 -0
  188. {pyhanko_cli-0.4.2 → pyhanko_cli-0.5.0}/pyhanko_testing_commons/test_data/data/pdf/malformed-xref-space-padded.pdf +0 -0
  189. {pyhanko_cli-0.4.2 → pyhanko_cli-0.5.0}/pyhanko_testing_commons/test_data/data/pdf/minimal-aes256-empty-encrypted-string.pdf +0 -0
  190. {pyhanko_cli-0.4.2 → pyhanko_cli-0.5.0}/pyhanko_testing_commons/test_data/data/pdf/minimal-aes256-malformed-oe.pdf +0 -0
  191. {pyhanko_cli-0.4.2 → pyhanko_cli-0.5.0}/pyhanko_testing_commons/test_data/data/pdf/minimal-aes256-malformed-perms.pdf +0 -0
  192. {pyhanko_cli-0.4.2 → pyhanko_cli-0.5.0}/pyhanko_testing_commons/test_data/data/pdf/minimal-aes256.pdf +0 -0
  193. {pyhanko_cli-0.4.2 → pyhanko_cli-0.5.0}/pyhanko_testing_commons/test_data/data/pdf/minimal-annotless.pdf +0 -0
  194. {pyhanko_cli-0.4.2 → pyhanko_cli-0.5.0}/pyhanko_testing_commons/test_data/data/pdf/minimal-badxref.pdf +0 -0
  195. {pyhanko_cli-0.4.2 → pyhanko_cli-0.5.0}/pyhanko_testing_commons/test_data/data/pdf/minimal-broken-xref-size.pdf +0 -0
  196. {pyhanko_cli-0.4.2 → pyhanko_cli-0.5.0}/pyhanko_testing_commons/test_data/data/pdf/minimal-hybrid-xref-mswordstyle.pdf +0 -0
  197. {pyhanko_cli-0.4.2 → pyhanko_cli-0.5.0}/pyhanko_testing_commons/test_data/data/pdf/minimal-hybrid-xref-weirdgen.pdf +0 -0
  198. {pyhanko_cli-0.4.2 → pyhanko_cli-0.5.0}/pyhanko_testing_commons/test_data/data/pdf/minimal-hybrid-xref.pdf +0 -0
  199. {pyhanko_cli-0.4.2 → pyhanko_cli-0.5.0}/pyhanko_testing_commons/test_data/data/pdf/minimal-illegal-header.pdf +0 -0
  200. {pyhanko_cli-0.4.2 → pyhanko_cli-0.5.0}/pyhanko_testing_commons/test_data/data/pdf/minimal-one-field-indir-annots.pdf +0 -0
  201. {pyhanko_cli-0.4.2 → pyhanko_cli-0.5.0}/pyhanko_testing_commons/test_data/data/pdf/minimal-pdf-ua-and-a.pdf +0 -0
  202. {pyhanko_cli-0.4.2 → pyhanko_cli-0.5.0}/pyhanko_testing_commons/test_data/data/pdf/minimal-pubkey-aes256.pdf +0 -0
  203. {pyhanko_cli-0.4.2 → pyhanko_cli-0.5.0}/pyhanko_testing_commons/test_data/data/pdf/minimal-pubkey-rc4-envelope.pdf +0 -0
  204. {pyhanko_cli-0.4.2 → pyhanko_cli-0.5.0}/pyhanko_testing_commons/test_data/data/pdf/minimal-pubkey-rc4.pdf +0 -0
  205. {pyhanko_cli-0.4.2 → pyhanko_cli-0.5.0}/pyhanko_testing_commons/test_data/data/pdf/minimal-pubkey-unknown-envelope-alg.pdf +0 -0
  206. {pyhanko_cli-0.4.2 → pyhanko_cli-0.5.0}/pyhanko_testing_commons/test_data/data/pdf/minimal-rc4.pdf +0 -0
  207. {pyhanko_cli-0.4.2 → pyhanko_cli-0.5.0}/pyhanko_testing_commons/test_data/data/pdf/minimal-signed-twice-both-created.pdf +0 -0
  208. {pyhanko_cli-0.4.2 → pyhanko_cli-0.5.0}/pyhanko_testing_commons/test_data/data/pdf/minimal-signed-twice-no-sig-type.pdf +0 -0
  209. {pyhanko_cli-0.4.2 → pyhanko_cli-0.5.0}/pyhanko_testing_commons/test_data/data/pdf/minimal-signed-twice-second-created.pdf +0 -0
  210. {pyhanko_cli-0.4.2 → pyhanko_cli-0.5.0}/pyhanko_testing_commons/test_data/data/pdf/minimal-startxref-hopeless.pdf +0 -0
  211. {pyhanko_cli-0.4.2 → pyhanko_cli-0.5.0}/pyhanko_testing_commons/test_data/data/pdf/minimal-startxref-hopeless2.pdf +0 -0
  212. {pyhanko_cli-0.4.2 → pyhanko_cli-0.5.0}/pyhanko_testing_commons/test_data/data/pdf/minimal-startxref-hopeless3.pdf +0 -0
  213. {pyhanko_cli-0.4.2 → pyhanko_cli-0.5.0}/pyhanko_testing_commons/test_data/data/pdf/minimal-startxref-obo1.pdf +0 -0
  214. {pyhanko_cli-0.4.2 → pyhanko_cli-0.5.0}/pyhanko_testing_commons/test_data/data/pdf/minimal-startxref-obo2.pdf +0 -0
  215. {pyhanko_cli-0.4.2 → pyhanko_cli-0.5.0}/pyhanko_testing_commons/test_data/data/pdf/minimal-startxref-obo3.pdf +0 -0
  216. {pyhanko_cli-0.4.2 → pyhanko_cli-0.5.0}/pyhanko_testing_commons/test_data/data/pdf/minimal-startxref-obo4.pdf +0 -0
  217. {pyhanko_cli-0.4.2 → pyhanko_cli-0.5.0}/pyhanko_testing_commons/test_data/data/pdf/minimal-startxref-obo5.pdf +0 -0
  218. {pyhanko_cli-0.4.2 → pyhanko_cli-0.5.0}/pyhanko_testing_commons/test_data/data/pdf/minimal-startxref-obo6.pdf +0 -0
  219. {pyhanko_cli-0.4.2 → pyhanko_cli-0.5.0}/pyhanko_testing_commons/test_data/data/pdf/minimal-startxref-same-line.pdf +0 -0
  220. {pyhanko_cli-0.4.2 → pyhanko_cli-0.5.0}/pyhanko_testing_commons/test_data/data/pdf/minimal-two-fields-aes256.pdf +0 -0
  221. {pyhanko_cli-0.4.2 → pyhanko_cli-0.5.0}/pyhanko_testing_commons/test_data/data/pdf/minimal-two-fields-pubkey-aes256.pdf +0 -0
  222. {pyhanko_cli-0.4.2 → pyhanko_cli-0.5.0}/pyhanko_testing_commons/test_data/data/pdf/minimal-two-fields-pubkey-rc4.pdf +0 -0
  223. {pyhanko_cli-0.4.2 → pyhanko_cli-0.5.0}/pyhanko_testing_commons/test_data/data/pdf/minimal-two-fields-signed-twice.pdf +0 -0
  224. {pyhanko_cli-0.4.2 → pyhanko_cli-0.5.0}/pyhanko_testing_commons/test_data/data/pdf/minimal-two-fields-tagged.pdf +0 -0
  225. {pyhanko_cli-0.4.2 → pyhanko_cli-0.5.0}/pyhanko_testing_commons/test_data/data/pdf/minimal-two-fields.pdf +0 -0
  226. {pyhanko_cli-0.4.2 → pyhanko_cli-0.5.0}/pyhanko_testing_commons/test_data/data/pdf/minimal-two-pages.pdf +0 -0
  227. {pyhanko_cli-0.4.2 → pyhanko_cli-0.5.0}/pyhanko_testing_commons/test_data/data/pdf/minimal-with-field-aes256.pdf +0 -0
  228. {pyhanko_cli-0.4.2 → pyhanko_cli-0.5.0}/pyhanko_testing_commons/test_data/data/pdf/minimal-with-field-pubkey-aes256.pdf +0 -0
  229. {pyhanko_cli-0.4.2 → pyhanko_cli-0.5.0}/pyhanko_testing_commons/test_data/data/pdf/minimal-with-field-pubkey-rc4.pdf +0 -0
  230. {pyhanko_cli-0.4.2 → pyhanko_cli-0.5.0}/pyhanko_testing_commons/test_data/data/pdf/minimal-with-field-rc4.pdf +0 -0
  231. {pyhanko_cli-0.4.2 → pyhanko_cli-0.5.0}/pyhanko_testing_commons/test_data/data/pdf/minimal-with-field-tagged.pdf +0 -0
  232. {pyhanko_cli-0.4.2 → pyhanko_cli-0.5.0}/pyhanko_testing_commons/test_data/data/pdf/minimal-with-field.pdf +0 -0
  233. {pyhanko_cli-0.4.2 → pyhanko_cli-0.5.0}/pyhanko_testing_commons/test_data/data/pdf/minimal-with-nonexistent-refs.pdf +0 -0
  234. {pyhanko_cli-0.4.2 → pyhanko_cli-0.5.0}/pyhanko_testing_commons/test_data/data/pdf/minimal-with-orphaned-xrefs.pdf +0 -0
  235. {pyhanko_cli-0.4.2 → pyhanko_cli-0.5.0}/pyhanko_testing_commons/test_data/data/pdf/minimal-with-simple-form.pdf +0 -0
  236. {pyhanko_cli-0.4.2 → pyhanko_cli-0.5.0}/pyhanko_testing_commons/test_data/data/pdf/minimal-with-textfield-group-var.pdf +0 -0
  237. {pyhanko_cli-0.4.2 → pyhanko_cli-0.5.0}/pyhanko_testing_commons/test_data/data/pdf/minimal-with-textfield-group.pdf +0 -0
  238. {pyhanko_cli-0.4.2 → pyhanko_cli-0.5.0}/pyhanko_testing_commons/test_data/data/pdf/minimal-xref.pdf +0 -0
  239. {pyhanko_cli-0.4.2 → pyhanko_cli-0.5.0}/pyhanko_testing_commons/test_data/data/pdf/minimal.pdf +0 -0
  240. {pyhanko_cli-0.4.2 → pyhanko_cli-0.5.0}/pyhanko_testing_commons/test_data/data/pdf/no-mediabox.pdf +0 -0
  241. {pyhanko_cli-0.4.2 → pyhanko_cli-0.5.0}/pyhanko_testing_commons/test_data/data/pdf/pades-lta-dss-indirect-arrs-test-2.pdf +0 -0
  242. {pyhanko_cli-0.4.2 → pyhanko_cli-0.5.0}/pyhanko_testing_commons/test_data/data/pdf/pades-lta-dss-indirect-arrs-test.pdf +0 -0
  243. {pyhanko_cli-0.4.2 → pyhanko_cli-0.5.0}/pyhanko_testing_commons/test_data/data/pdf/pades-with-old-style-signing-cert-attr-issser.pdf +0 -0
  244. {pyhanko_cli-0.4.2 → pyhanko_cli-0.5.0}/pyhanko_testing_commons/test_data/data/pdf/pades-with-old-style-signing-cert-attr.pdf +0 -0
  245. {pyhanko_cli-0.4.2 → pyhanko_cli-0.5.0}/pyhanko_testing_commons/test_data/data/pdf/page-tree-direct-kid.pdf +0 -0
  246. {pyhanko_cli-0.4.2 → pyhanko_cli-0.5.0}/pyhanko_testing_commons/test_data/data/pdf/pdf-background-test.pdf +0 -0
  247. {pyhanko_cli-0.4.2 → pyhanko_cli-0.5.0}/pyhanko_testing_commons/test_data/data/pdf/pdf-sig-with-econtent.pdf +0 -0
  248. {pyhanko_cli-0.4.2 → pyhanko_cli-0.5.0}/pyhanko_testing_commons/test_data/data/pdf/pubkey-3des-test.pdf +0 -0
  249. {pyhanko_cli-0.4.2 → pyhanko_cli-0.5.0}/pyhanko_testing_commons/test_data/data/pdf/pubkey-ecc-test.pdf +0 -0
  250. {pyhanko_cli-0.4.2 → pyhanko_cli-0.5.0}/pyhanko_testing_commons/test_data/data/pdf/pubkey-rc2-test.pdf +0 -0
  251. {pyhanko_cli-0.4.2 → pyhanko_cli-0.5.0}/pyhanko_testing_commons/test_data/data/pdf/safedocs/CompactedPDFSyntaxTest.pdf +0 -0
  252. {pyhanko_cli-0.4.2 → pyhanko_cli-0.5.0}/pyhanko_testing_commons/test_data/data/pdf/safedocs/SOURCE +0 -0
  253. {pyhanko_cli-0.4.2 → pyhanko_cli-0.5.0}/pyhanko_testing_commons/test_data/data/pdf/scribble-decomp.pdf +0 -0
  254. {pyhanko_cli-0.4.2 → pyhanko_cli-0.5.0}/pyhanko_testing_commons/test_data/data/pdf/scribble-in-arr.pdf +0 -0
  255. {pyhanko_cli-0.4.2 → pyhanko_cli-0.5.0}/pyhanko_testing_commons/test_data/data/pdf/scribble.pdf +0 -0
  256. {pyhanko_cli-0.4.2 → pyhanko_cli-0.5.0}/pyhanko_testing_commons/test_data/data/pdf/separate-annots-kids-indir.pdf +0 -0
  257. {pyhanko_cli-0.4.2 → pyhanko_cli-0.5.0}/pyhanko_testing_commons/test_data/data/pdf/sig-no-signed-attrs.pdf +0 -0
  258. {pyhanko_cli-0.4.2 → pyhanko_cli-0.5.0}/pyhanko_testing_commons/test_data/data/pdf/sig-with-ski-sid.pdf +0 -0
  259. {pyhanko_cli-0.4.2 → pyhanko_cli-0.5.0}/pyhanko_testing_commons/test_data/data/pdf/signed-encrypted-pubkey-with-catalog-ref.pdf +0 -0
  260. {pyhanko_cli-0.4.2 → pyhanko_cli-0.5.0}/pyhanko_testing_commons/test_data/data/pdf/simple-acroform-states-ap-indirect.pdf +0 -0
  261. {pyhanko_cli-0.4.2 → pyhanko_cli-0.5.0}/pyhanko_testing_commons/test_data/data/pdf/simple-acroform-states.pdf +0 -0
  262. {pyhanko_cli-0.4.2 → pyhanko_cli-0.5.0}/pyhanko_testing_commons/test_data/data/pdf/source +0 -0
  263. {pyhanko_cli-0.4.2 → pyhanko_cli-0.5.0}/pyhanko_testing_commons/test_data/data/pdf/struct-tree-circular-ref.pdf +0 -0
  264. {pyhanko_cli-0.4.2 → pyhanko_cli-0.5.0}/pyhanko_testing_commons/test_data/data/pdf/uncompressed-objstream-sample.pdf +0 -0
  265. {pyhanko_cli-0.4.2 → pyhanko_cli-0.5.0}/pyhanko_testing_commons/test_data/data/tl/COPYRIGHT +0 -0
  266. {pyhanko_cli-0.4.2 → pyhanko_cli-0.5.0}/pyhanko_testing_commons/test_data/data/tl/eu-lotl-old.xml +0 -0
  267. {pyhanko_cli-0.4.2 → pyhanko_cli-0.5.0}/pyhanko_testing_commons/test_data/data/tl/eu-lotl-pivot-282.xml +0 -0
  268. {pyhanko_cli-0.4.2 → pyhanko_cli-0.5.0}/pyhanko_testing_commons/test_data/data/tl/eu-lotl-pivot-300.xml +0 -0
  269. {pyhanko_cli-0.4.2 → pyhanko_cli-0.5.0}/pyhanko_testing_commons/test_data/data/tl/eu-lotl-pivot-335.xml +0 -0
  270. {pyhanko_cli-0.4.2 → pyhanko_cli-0.5.0}/pyhanko_testing_commons/test_data/data/tl/eu-lotl-pivot-341.xml +0 -0
  271. {pyhanko_cli-0.4.2 → pyhanko_cli-0.5.0}/pyhanko_testing_commons/test_data/data/tl/eu-lotl.xml +0 -0
  272. {pyhanko_cli-0.4.2 → pyhanko_cli-0.5.0}/pyhanko_testing_commons/test_data/data/tl/pre-reanchor.cert.pem +0 -0
  273. {pyhanko_cli-0.4.2 → pyhanko_cli-0.5.0}/pyhanko_testing_commons/test_data/data/tl/tsl-be-old.xml +0 -0
  274. {pyhanko_cli-0.4.2 → pyhanko_cli-0.5.0}/pyhanko_testing_commons/test_data/data/tl/tsl-be-v6.xml +0 -0
  275. {pyhanko_cli-0.4.2 → pyhanko_cli-0.5.0}/pyhanko_testing_commons/test_data/data/tl/tsl-ee.xml +0 -0
  276. {pyhanko_cli-0.4.2 → pyhanko_cli-0.5.0}/pyhanko_testing_commons/test_data/data/xml/bad-xml/SOURCE +0 -0
  277. {pyhanko_cli-0.4.2 → pyhanko_cli-0.5.0}/pyhanko_testing_commons/test_data/data/xml/bad-xml/cyclic.xml +0 -0
  278. {pyhanko_cli-0.4.2 → pyhanko_cli-0.5.0}/pyhanko_testing_commons/test_data/data/xml/bad-xml/dtd.xml +0 -0
  279. {pyhanko_cli-0.4.2 → pyhanko_cli-0.5.0}/pyhanko_testing_commons/test_data/data/xml/bad-xml/external.xml +0 -0
  280. {pyhanko_cli-0.4.2 → pyhanko_cli-0.5.0}/pyhanko_testing_commons/test_data/data/xml/bad-xml/external_file.xml +0 -0
  281. {pyhanko_cli-0.4.2 → pyhanko_cli-0.5.0}/pyhanko_testing_commons/test_data/data/xml/bad-xml/quadratic.xml +0 -0
  282. {pyhanko_cli-0.4.2 → pyhanko_cli-0.5.0}/pyhanko_testing_commons/test_data/data/xml/bad-xml/simple-ns.xml +0 -0
  283. {pyhanko_cli-0.4.2 → pyhanko_cli-0.5.0}/pyhanko_testing_commons/test_data/data/xml/bad-xml/simple.xml +0 -0
  284. {pyhanko_cli-0.4.2 → pyhanko_cli-0.5.0}/pyhanko_testing_commons/test_data/data/xml/bad-xml/xmlbomb.xml +0 -0
  285. {pyhanko_cli-0.4.2 → pyhanko_cli-0.5.0}/pyhanko_testing_commons/test_data/data/xml/bad-xml/xmlbomb2.xml +0 -0
  286. {pyhanko_cli-0.4.2 → pyhanko_cli-0.5.0}/pyhanko_testing_commons/test_data/data/xml/bad-xml/xmp-with-harmless-entity.xml +0 -0
  287. {pyhanko_cli-0.4.2 → pyhanko_cli-0.5.0}/pyhanko_testing_commons/test_data/samples.py +0 -0
  288. {pyhanko_cli-0.4.2 → pyhanko_cli-0.5.0}/pyhanko_testing_commons/test_utils/__init__.py +0 -0
  289. {pyhanko_cli-0.4.2 → pyhanko_cli-0.5.0}/pyhanko_testing_commons/test_utils/csc_utils/__init__.py +0 -0
  290. {pyhanko_cli-0.4.2 → pyhanko_cli-0.5.0}/pyhanko_testing_commons/test_utils/csc_utils/csc_dummy_client.py +0 -0
  291. {pyhanko_cli-0.4.2 → pyhanko_cli-0.5.0}/pyhanko_testing_commons/test_utils/layout_test_utils.py +0 -0
  292. {pyhanko_cli-0.4.2 → pyhanko_cli-0.5.0}/pyhanko_testing_commons/test_utils/pkcs11_utils/__init__.py +0 -0
  293. {pyhanko_cli-0.4.2 → pyhanko_cli-0.5.0}/pyhanko_testing_commons/test_utils/pkcs11_utils/config.py +0 -0
  294. {pyhanko_cli-0.4.2 → pyhanko_cli-0.5.0}/pyhanko_testing_commons/test_utils/pkcs11_utils/fixtures.py +0 -0
  295. {pyhanko_cli-0.4.2 → pyhanko_cli-0.5.0}/setup.cfg +0 -0
  296. {pyhanko_cli-0.4.2 → pyhanko_cli-0.5.0}/src/pyhanko/__main__.py +0 -0
  297. {pyhanko_cli-0.4.2 → pyhanko_cli-0.5.0}/src/pyhanko/cli/__init__.py +0 -0
  298. {pyhanko_cli-0.4.2 → pyhanko_cli-0.5.0}/src/pyhanko/cli/_ctx.py +0 -0
  299. {pyhanko_cli-0.4.2 → pyhanko_cli-0.5.0}/src/pyhanko/cli/cache.py +0 -0
  300. {pyhanko_cli-0.4.2 → pyhanko_cli-0.5.0}/src/pyhanko/cli/commands/__init__.py +0 -0
  301. {pyhanko_cli-0.4.2 → pyhanko_cli-0.5.0}/src/pyhanko/cli/commands/crypt.py +0 -0
  302. {pyhanko_cli-0.4.2 → pyhanko_cli-0.5.0}/src/pyhanko/cli/commands/fields.py +0 -0
  303. {pyhanko_cli-0.4.2 → pyhanko_cli-0.5.0}/src/pyhanko/cli/commands/signing/__init__.py +0 -0
  304. {pyhanko_cli-0.4.2 → pyhanko_cli-0.5.0}/src/pyhanko/cli/commands/signing/pkcs11_cli.py +0 -0
  305. {pyhanko_cli-0.4.2 → pyhanko_cli-0.5.0}/src/pyhanko/cli/commands/signing/simple.py +0 -0
  306. {pyhanko_cli-0.4.2 → pyhanko_cli-0.5.0}/src/pyhanko/cli/commands/signing/utils.py +0 -0
  307. {pyhanko_cli-0.4.2 → pyhanko_cli-0.5.0}/src/pyhanko/cli/commands/stamp.py +0 -0
  308. {pyhanko_cli-0.4.2 → pyhanko_cli-0.5.0}/src/pyhanko/cli/commands/validation/__init__.py +0 -0
  309. {pyhanko_cli-0.4.2 → pyhanko_cli-0.5.0}/src/pyhanko/cli/commands/validation/ltv.py +0 -0
  310. {pyhanko_cli-0.4.2 → pyhanko_cli-0.5.0}/src/pyhanko/cli/commands/validation/validate.py +0 -0
  311. {pyhanko_cli-0.4.2 → pyhanko_cli-0.5.0}/src/pyhanko/cli/plugin_api.py +0 -0
  312. {pyhanko_cli-0.4.2 → pyhanko_cli-0.5.0}/src/pyhanko/cli/py.typed +0 -0
  313. {pyhanko_cli-0.4.2 → pyhanko_cli-0.5.0}/src/pyhanko/cli/runtime.py +0 -0
  314. {pyhanko_cli-0.4.2 → pyhanko_cli-0.5.0}/src/pyhanko/cli/utils.py +0 -0
  315. {pyhanko_cli-0.4.2 → pyhanko_cli-0.5.0}/src/pyhanko_cli.egg-info/dependency_links.txt +0 -0
  316. {pyhanko_cli-0.4.2 → pyhanko_cli-0.5.0}/src/pyhanko_cli.egg-info/entry_points.txt +0 -0
  317. {pyhanko_cli-0.4.2 → pyhanko_cli-0.5.0}/src/pyhanko_cli.egg-info/top_level.txt +0 -0
  318. {pyhanko_cli-0.4.2 → pyhanko_cli-0.5.0}/tests/__init__.py +0 -0
  319. {pyhanko_cli-0.4.2 → pyhanko_cli-0.5.0}/tests/test_cli_field_mgmt.py +0 -0
  320. {pyhanko_cli-0.4.2 → pyhanko_cli-0.5.0}/tests/test_cli_plugins.py +0 -0
  321. {pyhanko_cli-0.4.2 → pyhanko_cli-0.5.0}/tests/test_cli_signing_pkcs11.py +0 -0
  322. {pyhanko_cli-0.4.2 → pyhanko_cli-0.5.0}/tests/test_cli_stamp.py +0 -0
  323. {pyhanko_cli-0.4.2 → pyhanko_cli-0.5.0}/tests/validation/__init__.py +0 -0
  324. {pyhanko_cli-0.4.2 → pyhanko_cli-0.5.0}/tests/validation/conftest.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: pyhanko-cli
3
- Version: 0.4.2
3
+ Version: 0.5.0
4
4
  Summary: CLI tools for stamping and signing PDF files
5
5
  Author-email: Matthias Valvekens <dev@mvalvekens.be>
6
6
  Maintainer-email: Matthias Valvekens <dev@mvalvekens.be>
@@ -27,8 +27,8 @@ Description-Content-Type: text/markdown
27
27
  License-File: LICENSE
28
28
  Requires-Dist: asn1crypto>=1.5.1
29
29
  Requires-Dist: tzlocal>=4.3
30
- Requires-Dist: pyhanko<0.37,>=0.36.1
31
- Requires-Dist: pyhanko-certvalidator<0.32,>=0.31.4
30
+ Requires-Dist: pyhanko<0.38,>=0.37.0
31
+ Requires-Dist: pyhanko-certvalidator<0.33,>=0.32.0
32
32
  Requires-Dist: pyyaml>=6.0
33
33
  Requires-Dist: certifi>=2023.5.7
34
34
  Requires-Dist: click!=8.2.0,>=8.1.3
@@ -0,0 +1,647 @@
1
+ """Support framework for the executable documentation samples (doctests).
2
+
3
+ This module exposes a single declarative entry point, :func:`make_doc_env`,
4
+ which takes a :class:`DocEnvSpec` parameter object and returns a mapping of
5
+ names to inject into a document's doctest globals. It is responsible for all
6
+ the boilerplate the samples themselves should not have to show:
7
+
8
+ * an isolated working directory, so literal ``open('document.pdf', 'rb')``
9
+ calls in the samples resolve against real files;
10
+ * materialised input files (sample PDFs) and signer key material (PEM and
11
+ PKCS#12) written to the placeholder paths the samples reference;
12
+ * network mocking for timestamping and revocation info, so samples that talk
13
+ to ``http://tsa.example.com`` or fetch OCSP/CRLs simply work;
14
+ * a bundle of injected helper symbols (test signers, timestampers and the
15
+ stand-in "remote service" callables used by the interrupted-signing
16
+ examples).
17
+
18
+ Everything is built on top of the existing test utilities
19
+ (:mod:`pyhanko_testing_commons.test_utils.signing_commons` and
20
+ :mod:`pyhanko_testing_commons.test_data.samples`), so the certomancer PKI,
21
+ canonical sample PDFs and key material are reused verbatim.
22
+ """
23
+
24
+ import asyncio
25
+ import enum
26
+ import os
27
+ import tempfile
28
+ from collections.abc import Awaitable, Callable, Mapping
29
+ from dataclasses import dataclass, field
30
+ from datetime import datetime, timedelta, timezone
31
+ from io import BytesIO
32
+ from pathlib import Path
33
+ from typing import (
34
+ Any,
35
+ )
36
+
37
+ import aiohttp
38
+ import aiohttp.web
39
+ import tzlocal
40
+ from asn1crypto import pem, tsp
41
+ from certomancer import PKIArchitecture
42
+ from certomancer.integrations.aiohttp_illusionist import AsyncIllusionist
43
+ from certomancer.registry import (
44
+ ArchLabel,
45
+ CertLabel,
46
+ EntityLabel,
47
+ KeyLabel,
48
+ ServiceLabel,
49
+ )
50
+ from cryptography.hazmat.primitives import serialization
51
+ from freezegun import freeze_time
52
+ from pyhanko.pdf_utils.incremental_writer import IncrementalPdfFileWriter
53
+ from pyhanko.sign import fields, signers, timestamps
54
+ from pyhanko.sign.signers.pdf_cms import ExternalSigner, SimpleSigner
55
+ from pyhanko_certvalidator import ValidationContext
56
+ from pyhanko_certvalidator.registry import SimpleCertificateStore
57
+
58
+ from pyhanko_testing_commons.test_data import samples
59
+ from pyhanko_testing_commons.test_data.certomancer_trust_lists import (
60
+ certomancer_pki_as_trusted_list,
61
+ )
62
+ from pyhanko_testing_commons.test_utils import signing_commons
63
+ from pyhanko_testing_commons.test_utils.live_http import live_pki_services
64
+
65
+ __all__ = [
66
+ 'EXAMPLE_DOMAIN',
67
+ 'FREEZE_DT',
68
+ 'DocEnv',
69
+ 'DocEnvSpec',
70
+ 'SignatureProfile',
71
+ 'SignedDocSpec',
72
+ 'SignerProvisioning',
73
+ 'SignerSpec',
74
+ 'TimestampSpec',
75
+ 'TrustListSpec',
76
+ 'TrustSpec',
77
+ 'make_doc_env',
78
+ 'run_with_seeded_lotl',
79
+ 'seed_lotl_cache',
80
+ 'teardown_doc_env',
81
+ ]
82
+
83
+
84
+ #: Single canonical domain from which every example URL is derived. The
85
+ #: samples display URLs under this domain, and the network mocks key off it.
86
+ EXAMPLE_DOMAIN = 'pyhanko.tests'
87
+
88
+ #: Fixed point in time at which the doctests run. Chosen to fall within the
89
+ #: validity window of the certomancer ``testing-ca`` material.
90
+ FREEZE_DT = datetime(2020, 8, 1, tzinfo=timezone.utc).astimezone(
91
+ tz=tzlocal.get_localzone()
92
+ )
93
+
94
+ #: Point in time at which samples that consume the *real* bundled EU trusted
95
+ #: lists run. Those are signed by actual EU trust service providers, whose
96
+ #: certificates postdate :data:`FREEZE_DT` by years; this instant sits within
97
+ #: their validity window instead. Refreshing the bundled lists may require
98
+ #: moving it.
99
+ REAL_TL_DT = datetime(2026, 3, 1, tzinfo=timezone.utc).astimezone(
100
+ tz=tzlocal.get_localzone()
101
+ )
102
+
103
+
104
+ class SignerProvisioning(enum.Enum):
105
+ """Ways in which signer key material is made available to a sample."""
106
+
107
+ PEM = 'pem'
108
+ """Separate ``key.pem`` + ``cert.pem`` (+ a CA chain file)."""
109
+
110
+ PKCS12 = 'pkcs12'
111
+ """A single bundled ``.pfx`` file."""
112
+
113
+
114
+ @dataclass(frozen=True)
115
+ class SignerSpec:
116
+ """Describes the signer key material to materialise on disk."""
117
+
118
+ cert: CertLabel = CertLabel('signer1')
119
+ """The certomancer certificate (and matching key) to provision."""
120
+
121
+ provisioning: SignerProvisioning = SignerProvisioning.PEM
122
+ """How the key material is laid out on disk."""
123
+
124
+ key_passphrase: bytes = b'secret'
125
+ """Passphrase protecting the private key / PKCS#12 bundle."""
126
+
127
+ key_path: str = 'path/to/signer/key.pem'
128
+ """Destination for the PEM-encoded private key."""
129
+
130
+ cert_path: str = 'path/to/signer/cert.pem'
131
+ """Destination for the PEM-encoded signer certificate."""
132
+
133
+ chain_path: str | None = 'path/to/relevant/certs.pem'
134
+ """Destination for the PEM-encoded CA chain, or ``None`` to skip it."""
135
+
136
+ pfx_path: str = 'signer.pfx'
137
+ """Destination for the PKCS#12 bundle."""
138
+
139
+
140
+ @dataclass(frozen=True)
141
+ class TrustSpec:
142
+ """Chain-of-trust configuration for validation samples."""
143
+
144
+ trust_root: CertLabel = CertLabel('root')
145
+ """Trust anchor used to validate signatures produced in the sample."""
146
+
147
+ fetch_revocation: bool = False
148
+ """Whether to register OCSP/CRL responders for live revocation fetching."""
149
+
150
+ cert_path: str | None = 'path/to/certfile'
151
+ """Destination for the PEM-encoded trust root, or ``None`` to skip it.
152
+ Samples that call ``load_cert_from_pemder('path/to/certfile')`` read it."""
153
+
154
+
155
+ @dataclass(frozen=True)
156
+ class TrustListSpec:
157
+ """ETSI trusted-list configuration for qualified-signature samples.
158
+
159
+ When present, a signed trusted list covering the architecture's PKI is
160
+ written to disk so a sample can build a
161
+ :class:`~pyhanko.sign.validation.qualified.tsp.TSPRegistry` from it, exactly
162
+ as it would from a real national trusted list.
163
+ """
164
+
165
+ tlso_entity: EntityLabel = EntityLabel('root')
166
+ """Entity in the test PKI that acts as trusted-list scheme operator and
167
+ signs the list."""
168
+
169
+ xml_path: str = 'trusted-list.xml'
170
+ """Destination for the signed trusted-list XML."""
171
+
172
+
173
+ @dataclass(frozen=True)
174
+ class TimestampSpec:
175
+ """Timestamping configuration for samples that embed timestamp tokens."""
176
+
177
+ service: ServiceLabel = ServiceLabel('tsa')
178
+ """Which TSA in the test PKI backs the mocked :data:`TSA_URL`."""
179
+
180
+
181
+ class SignatureProfile(enum.Enum):
182
+ """Profile of a pre-signed document materialised for validation samples."""
183
+
184
+ PLAIN = 'plain'
185
+ """A single, plain approval signature."""
186
+
187
+ PADES = 'pades'
188
+ """A PAdES baseline (B-B) signature, without embedded revocation info or a
189
+ timestamp (suitable for qualified-signature samples that fetch revocation
190
+ info live)."""
191
+
192
+ PADES_LTA = 'pades_lta'
193
+ """A PAdES B-LTA signature with embedded revocation info and a document
194
+ timestamp (suitable for long-term validation samples)."""
195
+
196
+
197
+ @dataclass(frozen=True)
198
+ class SignedDocSpec:
199
+ """Describes a pre-signed document to materialise for validation samples."""
200
+
201
+ path: str = 'document.pdf'
202
+ """Destination for the signed document."""
203
+
204
+ base_file: str = 'MINIMAL_ONE_FIELD'
205
+ """Source identifier for the unsigned base document (see
206
+ :func:`_resolve_source`); must contain an empty signature field."""
207
+
208
+ field_name: str = 'Sig1'
209
+ """Name of the signature field to fill."""
210
+
211
+ profile: SignatureProfile = SignatureProfile.PLAIN
212
+ """Which :class:`SignatureProfile` to produce."""
213
+
214
+ signer_cert: CertLabel = CertLabel('signer1')
215
+ """Certificate (within the architecture) of the signer."""
216
+
217
+ signer_key: KeyLabel = KeyLabel('signer1')
218
+ """Private key (within the architecture) used to sign."""
219
+
220
+ signer_chain: tuple[CertLabel, ...] = (
221
+ CertLabel('root'),
222
+ CertLabel('interm'),
223
+ )
224
+ """CA certificates to embed alongside the signature."""
225
+
226
+
227
+ @dataclass(frozen=True)
228
+ class DocEnvSpec:
229
+ """Declarative description of the environment a document's samples need.
230
+
231
+ Every field has a sane default, so ``DocEnvSpec()`` yields an isolated
232
+ working directory containing ``document.pdf`` plus PEM signer material for
233
+ the RSA ``testing-ca`` architecture.
234
+ """
235
+
236
+ certomancer_config: str = samples.CERTOMANCER_CONFIG_PATH
237
+ """Path to the certomancer configuration to load architectures from."""
238
+
239
+ arch: ArchLabel = ArchLabel('testing-ca')
240
+ """Architecture within that configuration to wire up."""
241
+
242
+ files: Mapping[str, str] = field(
243
+ default_factory=lambda: {'document.pdf': 'MINIMAL'}
244
+ )
245
+ """Maps destination file names to a source identifier (see
246
+ :func:`_resolve_source`)."""
247
+
248
+ signers: tuple[SignerSpec, ...] = (SignerSpec(),)
249
+ """Signer key material to provision. A document may need several layouts
250
+ (e.g. both PEM files and a PKCS#12 bundle); pass an empty tuple for none."""
251
+
252
+ signed_documents: tuple[SignedDocSpec, ...] = ()
253
+ """Pre-signed documents to materialise (for validation samples)."""
254
+
255
+ trust: TrustSpec | None = None
256
+ """Chain-of-trust configuration, or ``None``."""
257
+
258
+ trust_list: TrustListSpec | None = None
259
+ """ETSI trusted-list configuration for qualified-signature samples, or
260
+ ``None``."""
261
+
262
+ timestamping: TimestampSpec = TimestampSpec()
263
+ """Timestamping configuration, or ``None``."""
264
+
265
+
266
+ # Logical source names that resolve to asset files shipped with the test data,
267
+ # in addition to the byte constants exposed by the samples module.
268
+ _ASSET_SOURCES = {
269
+ 'NotoSans-Regular.ttf': samples.PDF_DATA_DIR
270
+ + '/../fonts/NotoSans-Regular.ttf',
271
+ 'stamp.png': samples.PDF_DATA_DIR + '/../img/stamp.png',
272
+ }
273
+
274
+
275
+ def _resolve_source(name: str) -> bytes:
276
+ """Resolve a ``files`` source identifier to raw bytes.
277
+
278
+ The identifier is looked up first as a ``bytes`` constant on the samples
279
+ module (e.g. ``'MINIMAL'``), then as a named asset file.
280
+ """
281
+ value = getattr(samples, name, None)
282
+ if isinstance(value, bytes):
283
+ return value
284
+ if name in _ASSET_SOURCES:
285
+ return samples.read_all(_ASSET_SOURCES[name])
286
+ raise KeyError(f"Unknown doctest file source: {name!r}")
287
+
288
+
289
+ @dataclass
290
+ class DocEnv:
291
+ """Live handle on a materialised doctest environment.
292
+
293
+ Held onto by the generated globals so that :func:`teardown_doc_env` can
294
+ restore the working directory and tear down the active mocks.
295
+ """
296
+
297
+ workdir: str
298
+ prev_cwd: str
299
+ globals: dict[str, Any]
300
+ _closers: list[Any]
301
+
302
+
303
+ def _write_file(path: str, data: bytes) -> None:
304
+ parent = os.path.dirname(path)
305
+ if parent:
306
+ os.makedirs(parent, exist_ok=True)
307
+ with open(path, 'wb') as outf:
308
+ outf.write(data)
309
+
310
+
311
+ def _provision_signer(arch: PKIArchitecture, spec: SignerSpec) -> None:
312
+ cert = arch.get_cert(spec.cert)
313
+ if spec.provisioning == SignerProvisioning.PKCS12:
314
+ p12 = arch.package_pkcs12(spec.cert, password=spec.key_passphrase)
315
+ _write_file(spec.pfx_path, p12)
316
+ return
317
+
318
+ key_info = arch.key_set.get_private_key(KeyLabel(str(spec.cert)))
319
+ private_key = serialization.load_der_private_key(
320
+ key_info.dump(), password=None
321
+ )
322
+ key_pem = private_key.private_bytes(
323
+ encoding=serialization.Encoding.PEM,
324
+ format=serialization.PrivateFormat.PKCS8,
325
+ encryption_algorithm=serialization.BestAvailableEncryption(
326
+ spec.key_passphrase
327
+ ),
328
+ )
329
+ _write_file(spec.key_path, key_pem)
330
+ _write_file(spec.cert_path, pem.armor('CERTIFICATE', cert.dump()))
331
+ if spec.chain_path is not None:
332
+ chain = b''.join(
333
+ pem.armor('CERTIFICATE', arch.get_cert(CertLabel(label)).dump())
334
+ for label in ('root', 'interm')
335
+ )
336
+ _write_file(spec.chain_path, chain)
337
+
338
+
339
+ def _build_signer(arch: PKIArchitecture, spec: SignedDocSpec) -> SimpleSigner:
340
+ return SimpleSigner(
341
+ signing_cert=arch.get_cert(spec.signer_cert),
342
+ signing_key=arch.key_set.get_private_key(spec.signer_key),
343
+ cert_registry=SimpleCertificateStore.from_certs(
344
+ arch.get_cert(label) for label in spec.signer_chain
345
+ ),
346
+ )
347
+
348
+
349
+ def _generate_signed_doc(
350
+ arch: PKIArchitecture, spec: SignedDocSpec, ts_spec: TimestampSpec | None
351
+ ) -> None:
352
+ """Produce a signed PDF and write it to ``spec.path``.
353
+
354
+ Must be called while the timestamp/revocation mocks and ``freeze_time`` are
355
+ active, since the B-LTA profile fetches revocation info and a timestamp.
356
+ """
357
+ base = _resolve_source(spec.base_file)
358
+ writer = IncrementalPdfFileWriter(BytesIO(base))
359
+ signer = _build_signer(arch, spec)
360
+ if spec.profile == SignatureProfile.PADES_LTA:
361
+ if not ts_spec:
362
+ raise ValueError("ts_spec must not be None")
363
+ root = arch.get_cert(CertLabel('root'))
364
+ meta = signers.PdfSignatureMetadata(
365
+ field_name=spec.field_name,
366
+ md_algorithm='sha256',
367
+ subfilter=fields.SigSeedSubFilter.PADES,
368
+ validation_context=ValidationContext(
369
+ trust_roots=[root], allow_fetching=True, other_certs=[]
370
+ ),
371
+ embed_validation_info=True,
372
+ use_pades_lta=True,
373
+ )
374
+ out = signers.sign_pdf(
375
+ writer,
376
+ meta,
377
+ signer=signer,
378
+ timestamper=timestamps.HTTPTimeStamper(
379
+ arch.service_registry.get_tsa_info(ts_spec.service).url
380
+ ),
381
+ existing_fields_only=True,
382
+ )
383
+ elif spec.profile == SignatureProfile.PADES:
384
+ out = signers.sign_pdf(
385
+ writer,
386
+ signers.PdfSignatureMetadata(
387
+ field_name=spec.field_name,
388
+ subfilter=fields.SigSeedSubFilter.PADES,
389
+ ),
390
+ signer=signer,
391
+ existing_fields_only=True,
392
+ )
393
+ else:
394
+ out = signers.sign_pdf(
395
+ writer,
396
+ signers.PdfSignatureMetadata(field_name=spec.field_name),
397
+ signer=signer,
398
+ existing_fields_only=True,
399
+ )
400
+ _write_file(spec.path, out.getvalue())
401
+
402
+
403
+ def _tsa_callback(request_body: bytes) -> bytes:
404
+ req = tsp.TimeStampReq.load(request_body)
405
+ return signing_commons.DUMMY_TS.request_tsa_response(req=req).dump()
406
+
407
+
408
+ def _make_async_runner(
409
+ arch: PKIArchitecture,
410
+ ) -> Callable[[Callable[[aiohttp.ClientSession], Awaitable[None]]], None]:
411
+ """Build the ``run_async_signing`` helper injected into the doctest globals.
412
+
413
+ The ``aiohttp`` sample factors its logic into a coroutine that performs
414
+ PAdES-LTA signing given an :class:`aiohttp.ClientSession`. The helper runs
415
+ that coroutine against a certomancer
416
+ :class:`~certomancer.integrations.aiohttp_illusionist.AsyncIllusionist`,
417
+ whose served session transparently answers the OCSP/CRL fetches and the
418
+ timestamp request the sample makes, so the example runs end to end.
419
+ """
420
+ illusionist = AsyncIllusionist(arch, at_time=FREEZE_DT)
421
+
422
+ def run_async_signing(
423
+ body: Callable[[aiohttp.ClientSession], Awaitable[None]],
424
+ ) -> None:
425
+ async def _main() -> None:
426
+ app = illusionist.build_app()
427
+ async with illusionist.serving_session(app=app) as session:
428
+ await body(session)
429
+
430
+ asyncio.run(_main())
431
+
432
+ return run_async_signing
433
+
434
+
435
+ def _make_standins(signer: SimpleSigner) -> dict:
436
+ """Build the stand-in "remote service" helpers used by the
437
+ interrupted-signing examples.
438
+
439
+ These mimic an external signing service by routing the cryptographic work
440
+ through the in-process ``testing-ca`` key material, so the visible samples
441
+ can keep referring to opaque ``call_external_service`` /
442
+ ``instantiate_external_signer`` helpers while still running end to end.
443
+ """
444
+
445
+ cert = signer.signing_cert
446
+ registry = signer.cert_registry
447
+
448
+ # A non-signing ExternalSigner for size estimation / signed-attr assembly,
449
+ # standing in for a remote signer whose certificate is known up front.
450
+ ext_signer = ExternalSigner(
451
+ signing_cert=cert,
452
+ cert_registry=registry,
453
+ signature_value=bytes(256),
454
+ )
455
+
456
+ async def sign_remotely(signed_attrs_data: bytes) -> bytes:
457
+ # The "remote service" signs the prepared signed attributes with the
458
+ # real private key, yielding a value the caller can plug back in.
459
+ return await signer.async_sign_raw(signed_attrs_data, 'sha256')
460
+
461
+ def instantiate_external_signer(sig_value: bytes) -> ExternalSigner:
462
+ return ExternalSigner(
463
+ signing_cert=cert,
464
+ cert_registry=registry,
465
+ signature_value=sig_value,
466
+ )
467
+
468
+ async def call_external_service(document_digest: bytes):
469
+ # Stand-in for a service that provisions a short-lived certificate and
470
+ # returns a complete CMS container given a document digest.
471
+ return await signer.async_sign(
472
+ document_digest,
473
+ digest_algorithm='sha256',
474
+ )
475
+
476
+ return {
477
+ 'ext_signer': ext_signer,
478
+ 'sign_remotely': sign_remotely,
479
+ 'instantiate_external_signer': instantiate_external_signer,
480
+ 'call_external_service': call_external_service,
481
+ }
482
+
483
+
484
+ def make_doc_env(spec: DocEnvSpec = DocEnvSpec()) -> dict:
485
+ """Materialise a doctest environment and return the doctest globals.
486
+
487
+ The returned mapping is meant to be fed to ``globals().update(...)`` in a
488
+ document's hidden ``.. testsetup:: *`` block. It contains the injected
489
+ helper symbols *and* a ``_doc_env`` handle consumed by
490
+ :func:`teardown_doc_env`.
491
+
492
+ :param spec:
493
+ Declarative description of the environment; see :class:`DocEnvSpec`.
494
+ :return:
495
+ A mapping of names to inject into the doctest globals.
496
+ """
497
+
498
+ arch = samples.CERTOMANCER.get_pki_arch(spec.arch)
499
+
500
+ prev_cwd = os.getcwd()
501
+ workdir = tempfile.mkdtemp(prefix='pyhanko-doctest-')
502
+ os.chdir(workdir)
503
+
504
+ closers: list[Any] = []
505
+ try:
506
+ freezer = freeze_time(FREEZE_DT)
507
+ freezer.start()
508
+ closers.append(freezer.stop)
509
+
510
+ needs_pades = any(
511
+ doc.profile == SignatureProfile.PADES_LTA
512
+ for doc in spec.signed_documents
513
+ )
514
+ register_services = (
515
+ spec.trust is not None and spec.trust.fetch_revocation
516
+ ) or needs_pades
517
+
518
+ services_cm = live_pki_services()
519
+ services = services_cm.__enter__()
520
+ closers.append(lambda: services_cm.__exit__(None, None, None))
521
+ services.post(
522
+ arch.service_registry.get_tsa_info(spec.timestamping.service).url,
523
+ content=_tsa_callback,
524
+ content_type='application/timestamp-reply',
525
+ )
526
+ if register_services:
527
+ services.register(arch)
528
+
529
+ for dest, source in spec.files.items():
530
+ _write_file(dest, _resolve_source(source))
531
+
532
+ for signer_spec in spec.signers:
533
+ _provision_signer(arch, signer_spec)
534
+
535
+ if spec.trust is not None and spec.trust.cert_path is not None:
536
+ trust_cert = arch.get_cert(spec.trust.trust_root)
537
+ _write_file(
538
+ spec.trust.cert_path,
539
+ pem.armor('CERTIFICATE', trust_cert.dump()),
540
+ )
541
+
542
+ if spec.trust_list is not None:
543
+ tl_xml = certomancer_pki_as_trusted_list(
544
+ arch, spec.trust_list.tlso_entity
545
+ )
546
+ _write_file(spec.trust_list.xml_path, tl_xml.encode('utf-8'))
547
+
548
+ for doc_spec in spec.signed_documents:
549
+ _generate_signed_doc(arch, doc_spec, spec.timestamping)
550
+
551
+ injected: dict[str, Any] = {
552
+ 'run_async_signing': _make_async_runner(arch),
553
+ 'run_with_seeded_lotl': run_with_seeded_lotl,
554
+ 'TSA_URL': arch.service_registry.get_tsa_info(
555
+ spec.timestamping.service
556
+ ).url,
557
+ }
558
+ injected.update(_make_standins(signing_commons.FROM_CA))
559
+ except Exception:
560
+ # Make sure a partially constructed environment doesn't leak the cwd
561
+ # change or any started mocks.
562
+ for closer in reversed(closers):
563
+ closer()
564
+ os.chdir(prev_cwd)
565
+ raise
566
+
567
+ env = DocEnv(
568
+ workdir=workdir,
569
+ prev_cwd=prev_cwd,
570
+ globals=injected,
571
+ _closers=closers,
572
+ )
573
+ injected['_doc_env'] = env
574
+ return injected
575
+
576
+
577
+ def teardown_doc_env(env: DocEnv) -> None:
578
+ """Tear down an environment produced by :func:`make_doc_env`.
579
+
580
+ Restores the previous working directory and stops the timestamp/revocation
581
+ mocks. Safe to call once per document in a ``.. testcleanup::`` block.
582
+
583
+ :param env:
584
+ The :class:`DocEnv` handle (typically referenced as ``_doc_env`` in the
585
+ doctest globals).
586
+ """
587
+ for closer in reversed(env._closers):
588
+ closer()
589
+ env._closers.clear()
590
+ os.chdir(env.prev_cwd)
591
+
592
+
593
+ def seed_lotl_cache(cache_dir: str | os.PathLike) -> str:
594
+ """Pre-seed a :class:`FileSystemTLCache` directory with the bundled EU
595
+ list-of-the-lists and the Belgian national trusted list.
596
+
597
+ This lets the live-bootstrap sample in the qualified-validation guide run
598
+ without touching the network: every download
599
+ :func:`~.pyhanko.sign.validation.qualified.eutl_fetch.lotl_to_registry`
600
+ would otherwise perform becomes a cache hit. Restricting the sample to a
601
+ single member state (``only_territories={'be'}``) keeps it fast and means
602
+ only the Belgian list has to be seeded alongside the LOTL itself.
603
+
604
+ :param cache_dir:
605
+ Directory to populate; created if it does not yet exist.
606
+ :return:
607
+ The cache directory as a string, handy for feeding straight back into
608
+ the sample.
609
+ """
610
+ from pyhanko.sign.validation.qualified.eutl_fetch import (
611
+ EU_LOTL_LOCATION,
612
+ FileSystemTLCache,
613
+ )
614
+
615
+ tl_dir = Path(samples.TEST_DIR) / 'data' / 'tl'
616
+ cache = FileSystemTLCache(
617
+ Path(cache_dir), expire_after=timedelta(days=3650)
618
+ )
619
+ cache[EU_LOTL_LOCATION] = (tl_dir / 'eu-lotl.xml').read_text(
620
+ encoding='utf8'
621
+ )
622
+ # The Belgian list's location as advertised in the bundled LOTL.
623
+ cache['https://tsl.belgium.be/tsl-be-v6.xml'] = (
624
+ tl_dir / 'tsl-be-v6.xml'
625
+ ).read_text(encoding='utf8')
626
+ return str(cache_dir)
627
+
628
+
629
+ def run_with_seeded_lotl(
630
+ body: Callable[[str], Awaitable[Any]], cache_dir: str = 'lotl-cache'
631
+ ) -> Any:
632
+ """Run a coroutine that bootstraps from the EU list-of-the-lists.
633
+
634
+ Seeds ``cache_dir`` through :func:`seed_lotl_cache` and runs ``body``
635
+ against it at :data:`REAL_TL_DT`, overriding the document's usual frozen
636
+ clock for the duration.
637
+
638
+ :param body:
639
+ Callable taking the cache directory and returning the coroutine to run.
640
+ :param cache_dir:
641
+ Directory to seed and hand to ``body``.
642
+ :return:
643
+ Whatever the coroutine returns.
644
+ """
645
+ with freeze_time(REAL_TL_DT):
646
+ seed_lotl_cache(cache_dir)
647
+ return asyncio.run(body(cache_dir))
@@ -409,6 +409,13 @@ pki-architectures:
409
409
  testing-ca-ed25519:
410
410
  template: testing-ca
411
411
  keyset: testing-ca-ed25519
412
+ certs:
413
+ signer1-indefinite:
414
+ subject: signer1
415
+ template: signer1
416
+ validity:
417
+ valid-from: "2020-01-01T00:00:00+0000"
418
+ valid-to: "9999-12-31T23:59:59+0000"
412
419
  services:
413
420
  time-stamping:
414
421
  tsa: