Dokumente auf elektronische Signatur überprüfen

Hey,
hat von euch schon einmal jemand über die API/DMS/OSREST ein Dokument auf das Vorhandensein einer elektronischen Signatur überprüft und hat eventuell einen Best Practice ?

Mein aktueller Ansatz wäre über einen Jobcall auf „std.GetDocumentDigest“ mit dem Parameter [CheckSignature] zu gehen.

Hoi @Globisch, geht es Dir um Signaturen mit dem Signaturmodul oder „nur“ um die internen Gratissignaturen von enaio® mit den Schlüsseln, welche OS bei der Lizenzerstellung mit erzeugt?

1 Like

Moin, @rk.
Es handelt sich um eine Signatur von Governikus also nicht die enaio eigene.

Hallo, das ist eine interessante Frage, ich selbst habe keinen Kunden, der dies aktiv einsetzt. Wenn Du dort auf einer Datei std.GetDocumentDigest aufrufst, hätte ich bisher immer gedacht, dass Du nur das Feedback zum enaio-Hash und der eingebauten enaio-Signatur bekommst. Aber eventuell ist Dein Gesprür richtig und die Governikus-Signatur wird von diesem Call beachtet.

Da der enaio-RichClient die mit Governikus signierten Dokumente, soweit ich weiss, mit einem eigenen Icon in Trefferlisten kennzeichnet, scheint dieser zu wissen, welche Dokumente signiert sind:

Ohne ein System zu haben, an dem ich das ausprobieren kann, ist mein Gefühl, dass die einfachste Art zu prüfen, ob Dokumente eine Signatur haben ein DMS.GetResultList inklusive des Systemfelds OBJECT_SIGNSTATE zu machen. Dieses scheint mir der richtige Ort für diese Art auskunft zu sein. Dies wäre dann z. B. mit Python und ecmind_blue_client/lol_query(...) möglich.

Hey @rk,

ich werde deinen und meinen Ansatz kommende Woche bei dem Kunden testen und dir Feedback geben.
Danke für das Brainstorming! :slight_smile:

1 Like

Also,

die std.GetDocumentDigest scheint die elektronische Signatur nicht zu erfassen.

configuration = CustomConfiguration("config.json")
client = Client(configuration.server, "Signature_Flag", configuration.user, configuration.password)
job = Job("std.GetDocumentDigest")

dwObjectID = Param("dwObjectID", ParamTypes.INTEGER, 1275)
job.append(dwObjectID)
dwObjectType = Param("dwObjectType",ParamTypes.INTEGER, 262197)
job.append(dwObjectType)
checkSignature = Param("CheckSignature", ParamTypes.BOOLEAN, True)
job.append(checkSignature)

response = client.execute(job)
print(response.values)

Ergebnis:
Es werden beide Dokumente ohne Signatur erkannt. Dokument zwei besitzt jedoch eine.

‚4D9ED417492047ADE7E648E17D04C2607F872E3F4D430A4BCD301056FC16A3B2‘}
{‚Signature‘: 1, ‚TableDigest‘: ‚2C11231782E222B628367E3861BCE2012D94B623911DFD060C110529FD594418‘}

1 Like

Hallo @Globisch, das ist schade. Hast Du noch die Möglichkeit, auf diesem System DMS.GetResultList zu testen, ob diese mit OBJECT_SIGNSTATE als QueryResultField mehr verrät?

hey,
@rk werde ich die Tage machen und hier ein Feedback dazu geben.

1 Like

Hey @rk,

ich habe jetzt auch noch einmal mit dms.GetResultList und dem Feld OBJECT_SIGNSTATE getestet. Leider bleibt das Systemfeld trotz der Unterschrift durch Governikus auch hier leer.

Wenn dir nichts mehr einfällt, würde ich mich mal an OSB wenden, ob es eine andere Möglichkeit gibt.

Das untenstehende XML enthält die Signatur, die auch in Adobe sichtbar ist.

Der Kunde hat mir das Dokument zur Verfügung gestellt, damit ich unabhängig testen kann.

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>\r\n<DMSContent format="LOL" output_language="0" version="10.10.773.22129" timest amp="2024-11-15T10:38:41" user="DEV-ADMIN" station="OSVK-EXT-REST" instance="Signature_Flag">
	<Archive name="Verwaltungsakte" id="22" osguid="CB9F8B4285814F2696B25C176237B494">
		<ObjectType name="Dokument" id="262197" maintype="4" cotype="53" osguid="0AFFA84B143C45C4BC54ABC75CE84187" internal_name="Dokument" type="DOCUMENT" modul="MULTIDOC" table="object106">
			<Rowset>
				<Columns>
					<Column object="Dokument" type="DOCUMENT" name="signstate" internal_name="OBJECT_SIGNSTATE" system="1" datatype="INTEGER" dbname="signstate" ostype="9" osguid="1906" size="10">OBJECT_SIGNSTATE</Column>
					<Column object="Dokument" type="DOCUMENT" name="Titel" internal_name="OSTPL_DOCTITLE" datatype="TEXT" dbname="feld4" ostype="X" osguid="3DF2F366296242A5BB582E6118EB0E34" size="250">Titel</Column>
				</Columns>
				<Rows>
					<Row id="1275">
						<Value/>
						<Value>Signatur</Value>
					</Row>
				</Rows>
			</Rowset>
			<Statistics startpos="0" pagesize="-1" total_hits="1"/>
		</ObjectType>
	</Archive>
	<Messages/>
</DMSContent>


<?xml version="1.0" encoding="UTF-8" standalone="yes"?>\r\n<DMSContent format="LOL" output_language="0" version="10.10.773.22129" timest amp="2024-11-15T11:13:41" user="DEV-ADMIN" station="OSVK-EXT-REST" instance="Signature_Flag">
	<Archive name="Verwaltungsakte" id="22" osguid="CB9F8B4285814F2696B25C176237B494">
		<ObjectType name="Dokument" id="262197" maintype="4" cotype="53" osguid="0AFFA84B143C45C4BC54ABC75CE84187" internal_name="Dokument" type="DOCUMENT" modul="MULTIDOC" table="object106">
			<Rowset>
				<Columns>
					<Column object="Dokument" type="DOCUMENT" name="signstate" internal_name="OBJECT_SIGNSTATE" system="1" datatype="INTEGER" dbname="signstate" ostype="9" osguid="1906" size="10">OBJECT_SIGNSTATE</Column>
					<Column object="Dokument" type="DOCUMENT" name="Titel" internal_name="OSTPL_DOCTITLE" datatype="TEXT" dbname="feld4" ostype="X" osguid="3DF2F366296242A5BB582E6118EB0E34" size="250">Titel</Column>
				</Columns>
				<Rows>
					<Row id="1276">
						<Value/>
						<Value>40 Umlauf02 Sonstiges -  -  - Baubeschreibung_2022_12_12_PDFA.pdf - Nein - Nein -</Value>
					</Row>
				</Rows>
			</Rowset>
			<Statistics startpos="0" pagesize="-1" total_h its="1"/>
		</ObjectType>
	</Archive>
	<Messages/>
</DMSContent>
dms_query = ET.Element("DMSQuery")
archive = ET.SubElement(dms_query, "Archive", internal_name=folder)
object_type = ET.SubElement(archive, "ObjectType", internal_name=document, type="DOCUMENT")
fields = ET.SubElement(object_type, "Fields", field_schema="DEF")
ET.SubElement(fields, "Field", internal_name="OBJECT_SIGNSTATE", system='1')
ET.SubElement(fields, "Field", internal_name="OSTPL_DOCTITLE")
conditions = ET.SubElement(object_type, "Conditions")
condition_object = ET.SubElement(conditions, "ConditionObject", internal_name=document, Type="DOCUMENT")
field_condition = ET.SubElement(condition_object, "FieldCondition", internal_name="OBJECT_ID", system="1", operator="=")
ET.SubElement(field_condition, "Value").text = osid

xml_byte = ET.tostring(dms_query, encoding="utf-8")
xml_string = xml_byte.decode("utf-8")
job = Job(
    jobname="dms.GetResultList",
    XML=xml_string,
    FLAGS=0,
    ENCODING="utf-8",
)
response = client.execute(job)
print(response)

Hoi @Globisch, ach, vielleicht habe ich Dich die ganze Zeit missverstanden. Handelt es sich nicht um eine externe Signatur (=separate Datei, etwas, was das DMS verwaltet), sondern hast Du PDFs, welche intern signiert sind (=PDF hat eine selbsttragende Signatur)?

Ich glaube nicht, dass der Rendition Service von enaio das prüft und es gibt meines Wissens nach auch keine separate Queue dafür (anders als etwa Pagecount).

Deshalb müsstest Du hier vermutlich den Dokumenttyp mit einem Auswahlfeld [zur Prüfung, unsigniert, signiert, Fehler] ausstatten, bei StoreInWork auf zur Prüfung stellen und mit einem regelmässigen Job PDFs suchen, welche auf zur Prüfung stehen und beispielsweise mit der has_signature-Methode der borb-Bibliothek (siehe python - Check if a pdf is signed or not - Stack Overflow) durcharbeiten. Oder natürlich eine vergleichbare Logik.

Moin @rk,

es geht um ein PDF, das seine Signatur durch Governikus/Unterschriftenpad erhalten hat. Eine OS-Niederlassung hat hier einen Client zum Signieren entwickelt, der in enaio integriert ist, aber möglicherweise nicht bedacht, dass die Signatur später auch wieder gesucht oder anderweitig ermittelt werden muss.
Aus meiner Sicht hätte man dies bereits direkt über den Client lösen können.

Dass ich die Signaturen selbst ermitteln könnte, hatte ich schon als Plan B vorgesehen, und dazu wurde auch bereits eine Diskussion mit OSB geführt. Wenn man im Hinterkopf hat das der Signaturclient diese Info eigentlich schon mitgeben könnte, empfinde ich diesen Ansatz als recht aufwändig.

Ich werde mich nochmals mit OSB abstimmen, um zu klären, ob die Lösung künftig dahingehend angepasst werden kann. Vermutlich wird es jedoch zunächst auf den genannten Workaround hinauslaufen.

Das konkrete Szenario ist, dass der Kunde mehrere Millionen Dokumente besitzt und diese mit dem PDF-Dispatcher und Foxit zu PDF/A konvertieren soll. Die PDFs mit Signatur sollen jedoch ausgeklammert werden, da Foxit die Signaturen möglicherweise ungültig machen könnte.

1 Like