Compare commits

..

No commits in common. "3716c3ce78e02bf0df70193ba214e9ac30337d38" and "9f085484f792aab5f7852d823016a4af161094d2" have entirely different histories.

8 changed files with 14 additions and 180 deletions

View File

@ -7,15 +7,11 @@ from pyhanko.sign import signers, timestamps, fields
from pyhanko_certvalidator import ValidationContext from pyhanko_certvalidator import ValidationContext
from typing_extensions import Buffer from typing_extensions import Buffer
from pythonProject.timestamp import LocalOpensslTimestamp
class SignOrchestrator: class SignOrchestrator:
"""Orchestrate the signature on document""" """Orchestrate the signature on document"""
def __init__(self, pkcs12_path: str, def __init__(self, pkcs12_path: str, timestamp_url: str, pkcs12_password: Optional[bytes] = None):
tsa_config_path: str, tsa_password: str, tsa_cert_chain: str,
pkcs12_password: Optional[bytes] = None):
# Load signer key material from PKCS#12 file # Load signer key material from PKCS#12 file
# This assumes that any relevant intermediate certs are also included # This assumes that any relevant intermediate certs are also included
# in the PKCS#12 file. # in the PKCS#12 file.
@ -24,7 +20,9 @@ class SignOrchestrator:
) )
# Set up a timestamping client to fetch timestamps tokens # Set up a timestamping client to fetch timestamps tokens
self.timestamper = LocalOpensslTimestamp(tsa_config_path, tsa_password, tsa_cert_chain) self.timestamper = timestamps.HTTPTimeStamper(
url=timestamp_url,
)
self.stamp_style = stamp.TextStampStyle( self.stamp_style = stamp.TextStampStyle(
stamp_text="Signé par:\n%(signer_text)s\nLe %(ts)s", stamp_text="Signé par:\n%(signer_text)s\nLe %(ts)s",

View File

@ -1,16 +1,6 @@
from sign import SignOrchestrator from sign import SignOrchestrator
""" orchestrator = SignOrchestrator('./assets/dummy.p12','http://freetsa.org/tsr', pkcs12_password=None)
This is a script to sign a file with the dummy assets
It is created mainly for testing purpose
"""
orchestrator = SignOrchestrator('./assets/dummy.p12',
'/home/julien/dev/chill/sign-pdf-worker/ts-authority/rootca.conf',
'5678',
'/home/julien/dev/chill/sign-pdf-worker/ts-authority/ca/tsa-chain.pem',
pkcs12_password=None)
with open('./assets/test.pdf', 'rb') as input: with open('./assets/test.pdf', 'rb') as input:
signed_content = orchestrator.sign(reason="first signer", signature_index=0, signed_content = orchestrator.sign(reason="first signer", signature_index=0,
@ -21,9 +11,9 @@ with open('./assets/test.pdf', 'rb') as input:
output.write(signed_content.read()) output.write(signed_content.read())
with open('./assets/test_signed_0.pdf', 'rb') as input: with open('./assets/test_signed_0.pdf', 'rb') as input:
signed_content = orchestrator.sign(reason="second signer", signature_index=1, signed_content = orchestrator.sign(reason="second signer", signature_index=1,
input_content=input.read(), box_place=(100, 600, 300, 660), on_page=0, input_content=input.read(), box_place=(100, 600, 300, 660), on_page=0,
signer_text="M. Bah Mamadou") signer_text="M. Bah Mamadou")
with open('./assets/test_signed_1.pdf', 'wb') as output: with open('./assets/test_signed_1.pdf', 'wb') as output:
output.write(signed_content.read()) output.write(signed_content.read())

View File

@ -1,29 +0,0 @@
from sign import SignOrchestrator
"""
This is a script to sign a file with the dummy assets
It is created mainly for testing purpose
"""
orchestrator = SignOrchestrator('/run/user/1000/ca/cachet.p12',
'/home/julien/dev/chill/sign-pdf-worker/ts-authority/vendee-tsa.conf',
'xxxxxxxxxxxxxxxxxxx',
'/run/user/1000/ca/tsa-chain.pem',
pkcs12_password=b"xxxxxxxxxxxxxxxx")
with open('./assets/test.pdf', 'rb') as input:
signed_content = orchestrator.sign(reason="first signer", signature_index=0,
input_content=input.read(), box_place=(300, 600, 500, 660), on_page=0,
signer_text="Mme Caroline Diallo")
with open('./assets/test_signed_0.pdf', 'wb') as output:
output.write(signed_content.read())
with open('./assets/test_signed_0.pdf', 'rb') as input:
signed_content = orchestrator.sign(reason="second signer", signature_index=1,
input_content=input.read(), box_place=(100, 600, 300, 660), on_page=0,
signer_text="M. Bah Mamadou")
with open('./assets/test_signed_1.pdf', 'wb') as output:
output.write(signed_content.read())

View File

@ -1,64 +0,0 @@
import logging
import os
from asn1crypto import tsp
from asn1crypto.tsp import TimeStampResp
from pyhanko.sign.timestamps import TimeStamper
import subprocess
LOGGER = logging.getLogger(__name__)
LOGGER.setLevel(os.environ.get('LOG_LEVEL', logging.DEBUG))
class LocalOpensslTimestamp(TimeStamper):
"""
Apply a timestamp using a local openssl cli.
The class provides methods to request a timestamp response from a local OpenSSL TSA cli.
"""
def __init__(self, path_config: str, password: str, path_chain: str):
super().__init__()
self.path_conf = path_config
self.password = password
self.path_chain = path_chain
def request_tsa_response(self, req: tsp.TimeStampReq) -> tsp.TimeStampResp:
with open('/tmp/request.tsq', 'wb') as request:
request.write(req.dump())
cmd = [
'openssl', 'ts', '-reply',
'-config', self.path_conf,
'-queryfile', '/tmp/request.tsq',
'-chain', self.path_chain,
'-out', '/tmp/response.tsr',
'-passin', f'pass:{self.password}'
]
try:
subprocess.run(cmd, capture_output=True, check=True, timeout=10)
except subprocess.CalledProcessError as e:
LOGGER.error("Could not generate a timestamp")
LOGGER.error(f"response code: {e.returncode}")
LOGGER.error(f"stderr: {e.stderr}")
LOGGER.error(f"stdout: {e.stdout}")
LOGGER.error(f"error: {e.output}")
raise Exception("could not generate a timestamp")
except subprocess.TimeoutExpired as e:
LOGGER.error("timeout expired")
LOGGER.error(f"stderr: {e.stderr}")
LOGGER.error(f"stdout: {e.stdout}")
LOGGER.error(f"error: {e.output}")
raise e
with open('/tmp/response.tsr', mode='rb') as f:
tsp = TimeStampResp.load(f.read())
os.unlink('/tmp/response.tsr')
return tsp
async def async_request_tsa_response(self, req: tsp.TimeStampReq) -> tsp.TimeStampResp:
return self.request_tsa_response(req)

View File

@ -19,14 +19,13 @@ for v in ['AMQP_URL', 'PKCS12_PATH', 'TIMESTAMP_URL', 'QUEUE_IN', 'EXCHANGE_OUT'
DSN = os.environ.get('AMQP_URL') DSN = os.environ.get('AMQP_URL')
PKCS12_PATH = os.environ.get('PKCS12_PATH') PKCS12_PATH = os.environ.get('PKCS12_PATH')
TIMESTAMP_URL = os.environ.get('TIMESTAMP_URL')
QUEUE_IN = os.environ.get('QUEUE_IN') QUEUE_IN = os.environ.get('QUEUE_IN')
EXCHANGE_OUT = os.environ.get('EXCHANGE_OUT') EXCHANGE_OUT = os.environ.get('EXCHANGE_OUT')
OUT_ROUTING_KEY = os.environ.get('OUT_ROUTING_KEY') OUT_ROUTING_KEY = os.environ.get('OUT_ROUTING_KEY')
TSA_CONFIG_PATH = os.environ.get('TSA_CONFIG_PATH')
TSA_CERT_CHAIN = os.environ.get('TSA_CERT_CHAIN')
TSA_KEY_PASSWORD = os.environ.get('TSA_KEY_PASSWORD')
orchestrator = sign.SignOrchestrator(PKCS12_PATH, TSA_CONFIG_PATH, TSA_KEY_PASSWORD, TSA_CERT_CHAIN, pkcs12_password=os.environ.get('PKCS12_PASSWORD', None))
orchestrator = sign.SignOrchestrator(PKCS12_PATH, TIMESTAMP_URL, pkcs12_password=os.environ.get('PKCS12_PASSWORD', None))
parameters = pika.URLParameters(DSN) parameters = pika.URLParameters(DSN)
connection = pika.BlockingConnection(parameters) connection = pika.BlockingConnection(parameters)

View File

@ -151,17 +151,3 @@ The OK response ensures that the original signed timestamp is correctly authoriz
openssl ts -verify -data /etc/hosts -in /tmp/response.tsr -CAfile ca/root-ca.pem -untrusted ca/tsa.pem openssl ts -verify -data /etc/hosts -in /tmp/response.tsr -CAfile ca/root-ca.pem -untrusted ca/tsa.pem
``` ```
# Préparation pour Vendée
## Extraire les infos
```bash
openssl pkcs12 -info -in horodatage.p12 -legacy
```
Ca demandera un mot de passe pour déchiffrer, et un autre mot de passe pour chiffrer la clé qui apparaitra.
- on recopie la clé et on fait un copier-coller dans /run/user/1000/ca/private/tsa.key
- on recopie tous les certificats, on supprime les interligne, et on colle ça dans /run/user/1000/ca/tsa-chain.pem
- on recopie le premier certificat, pour céer /run/user/1000/ca/tsa.crt

View File

@ -138,7 +138,7 @@ subjectKeyIdentifier = hash
default_tsa = tsa_config1 default_tsa = tsa_config1
[ tsa_config1 ] [ tsa_config1 ]
dir = /home/julien/dev/chill/sign-pdf-worker/ts-authority # TSA root directory, same as root-ca dir = . # TSA root directory, same as root-ca
serial = $dir/ca/tsa_serial # current serial number (mandatory) serial = $dir/ca/tsa_serial # current serial number (mandatory)
signer_cert = $dir/ca/tsa.crt # signing certificate (optional) signer_cert = $dir/ca/tsa.crt # signing certificate (optional)
certs = $dir/ca/tsa-chain.pem # certification chain (optional) certs = $dir/ca/tsa-chain.pem # certification chain (optional)

View File

@ -1,46 +0,0 @@
#
# rootca.conf
#
# See Ristic OpenSSL Cookbook URL above.
oid_section = new_oids
[ new_oids ]
tsa_policy1 = 1.2.3.4.1
tsa_policy2 = 1.2.3.4.5.6
tsa_policy3 = 1.2.3.4.5.7
[ tsa ]
default_tsa = tsa_config1
[ tsa_config1 ]
dir = /run/user/1000/ca # TSA root directory, same as root-ca
serial = $dir/tsa_serial # current serial number (mandatory)
signer_cert = $dir/tsa.crt # signing certificate (optional)
certs = $dir/tsa-chain.pem # certification chain (optional)
signer_key = $dir/private/tsa.key # tsa private key (optional)
default_policy = tsa_policy1
signer_digest = sha256 # digest to use for signing (optional)
other_policies = tsa_policy2,tsa_policy3 # other policies (optional)
digests = sha256,sha384,sha512 # acceptable digests (mandatory)
accuracy = secs:1,millisecs:500,microsecs:100 # accuracy optional
ordering = yes # is ordering defined? (optional, default: no)
tsa_name = yes # must tsa name be included in reply? (opt., default: no)
ess_cert_id_chain = yes # must ess cert id change be incl? (opt., default: no)
ess_cert_id_alg = sha256 # alg to compute cert. id (optional, default: sha1)
# added, was missing in the blog post
crypto_device = builtin
# The tsa_ext extension is
# used to create the tsa cert tsa.crt
[ tsa_ext ]
authorityKeyIdentifier = keyid:always
basicConstraints = critical,CA:false
extendedKeyUsage = critical,timeStamping
keyUsage = critical,nonRepudiation
subjectKeyIdentifier = hash