Neu vorgestellt, Programmierung

Signieren mit CONZEPT 16

Digitale Signaturen kommen in vielen Gebieten, in denen Authentizität und Integrität eine wichtige Rolle spielen zum Einsatz. Beispiele sind E-Mails, Rechnungen oder elektronische Ausweise. Im Zuge dessen wird es in der kommenden CONZEPT 16-Version 5.7.08 möglich sein, digitale Signaturen zu erstellen und zu verifizieren.


Allgemeines

Eine digitale Signatur ist eine elektronische Sicherheitskennzeichnung, mit der sichergestellt werden soll, dass eine Nachricht tatsächlich vom angegebenen Absender stammt und dass der Inhalt seit dem Erstellen der Signatur nicht verändert wurde.

Die Erstellung einer Signatur verwendet ein asymmetrisches Kryptoverfahren, bei dem zunächst der Hash-Wert der zu übermittelnden Nachricht berechnet wird. Dieser Hash-Wert wird anschließend mit einem privaten Schlüssel verschlüsselt und das Ergebnis an die Nachricht angehängt.

Der Empfänger der Nachricht kann die Signatur mit dem zugehörigen öffentlichen Schlüssel verifizieren. Dazu wird aus der Nachricht erneut der Hash-Wert berechnet. Anschließend wird der angehängte, verschlüsselte Hash-Wert mit dem öffentlichen Schlüssel des Absenders entschlüsselt. Stimmen die beiden ermittelten Hash-Werte überein, lässt sich daraus schließen, dass der Absender korrekt ist und die Nachricht nicht von Dritten verändert wurde.

Das ganze System setzt allerdings voraus, dass ausschließlich die autorisierten Signatur-Ersteller im Besitz des privaten Schlüssels sind. Eine klare Zuordnung des privaten Schlüssels zu einer Person kann beispielsweise durch ein Zertifikat geschehen.

Die Ver- und Entschlüsselung von Signaturen kann in CONZEPT 16 mit den beiden asymmetrischen Verfahren RSA oder DSA erfolgen. Für die Hash-Werte sind die Methoden MD5, Ripe-MD, SHA-1 und SHA-2 verfügbar.

Signatur erzeugen

Der Befehl zum Signieren lautet MemSign() und ist wie folgt definiert:

MemSign(
    aMem       : handle  // Memory-Objekt mit Nachricht
    aOptions   : int     // Optionen
    aKey       : alpha   // Privater Schlüssel
    vSignature : alpha   // Out:Signatur
opt aPos       : int     // Nachrichtenposition im Memory-Objekt
opt aLen       : int     // Länge der Nachricht im Memory-Objekt
)
: int                    // Fehlerwert

In aMem wird ein Memory-Objekt übergeben, welches die zu signierende Nachricht enthält.

In aOptions erfolgt die Auswahl der Algorithmen für die vier Bereiche Signatur-Algorithmus, Hash-Algorithmus, Kodierung des privaten Schlüssels und die Kodierung der Signatur.

  • Signatur-Algorithmus
    _MemSignRSA, _MemSignDSA
  • Hash-Algorithmus
    _MemHashMD5, _MemHashRMD160, _MemHashSHA1, _MemHashSHA256, _MemHashSHA384, _MemHashSHA512
  • Schlüsselkodierung
    _MemKeyHex, _MemKeyBase64
  • Signaturkodierung
    _MemResultHex, _MemResultBase64

In aKey wird der private Schlüssel übergeben. Dieser kann in den Formaten PKCS #1 oder PKCS #8 vorliegen.

vSignature ist ein Referenzargument und enthält beim erfolgreichen Signieren die Signatur, andernfalls einen Leerstring.

Die Argumente aPos und aLen sind optional und werden dazu verwendet, den Bereich im Memory-Objekt anzugeben, der die zu signierende Nachricht enthält.

War das Signieren erfolgreich, liefert die Funktion MemSign() _ErrOK zurück. Andernfalls kann einer der folgenden Fehlerwerte zurückgegegeben werden:

  • _ErrMemKeyInvalid
    Der Fehler tritt auf, wenn zum Beispiel ein RSA-Key erwartet wird, jedoch ein anderer (ungültiger) Key angegeben wurde, oder wenn die Dekodierung des Schlüssels fehlschlug.
  • _ErrMemKeyLength
    Der angegebene Schlüssel ist zu kurz, um die Nachricht zu signieren.

Mit folgendem Beispiel kann eine Signatur erzeugt werden:

// ...

tErg # tMem->MemSign(
             _MemSignDSA |      // Es soll eine DSA-Signatur erzeugt werden
             _MemHashSHA1 |     // SHA1-Hash
             _MemKeyBase64 |    // Key ist Base64-Kodiert
             _MemResultBase64 | // Signatur wird Base64-Kodiert
             tPrivateKey,       // Privater Schlüssel
             var tSignature,    // Signatur wird in tSignature abgelegt
);

// Signatur ausgeben
WinDialogBox(0, 'Signatur', tSignature, _WinIcoInformation, _WinDialogOk, 0);

// ...
Signatur verifizieren

Der Befehl MemVerify() hat ebenfalls 6 Parameter,

MemVerify(
      aMem       : handle  // Memory-Objekt mit Nachricht
      aOptions   : int     // Optionen
      aKey       : alpha   // Öffentlicher Schlüssel
      aSignature : alpha   // Signatur, die verifziert werden soll
  opt aPos       : int     // NAchrichtenpoistion im Memory-Objekt
  opt aLen       : int     // Länge der Nachricht im Memory-Objekt
)
: int                      // Fehlerwert

die sich in drei Punkten zu MemSign() unterscheiden:

  • aOptions definiert die Kodierung der angegebenen Signatur mit den Konstanten _MemSignatureHex oder _MemSignatureBase64.
  • aKey beinhaltet den öffentlichen Schlüssel im X509-Format. RSA-Schlüssel können auch im Format PKCS #1 angegeben werden.
  • In aSignature wird die zu verifizierende Signatur übergeben.

War die Verifizierung erfolgreich, gibt die Funktion MemVerify() _ErrOK zurück. Andernfalls wird eine der folgenden Werte zurückgegeben:

  • _ErrMemMsgVerify
    Die Signatur passt nicht zum Schlüssel.
  • _ErrMemSgnInvalid
    Das Dekodieren der Signatur schlug fehl oder die Signatur ist ungültig.
  • _ErrMemKeyInvalid
    Das Dekodieren des Schlüssels schlug fehl oder der Schlüssel ist ungültig.

Ein Beispiel zur Verifikaiton:

// ...

tErr # tMem->MemVerify(
             _MemSignDSA |        // DSA-Signatur liegt vor
             _MemHashSHA1 |       // SHA1-Hash muss verwendet werden, da Signatur mit SHA1 erzeugt wurde
             _MemKeyBase64 |      // Key ist Base64-Kodiert
             _MemSignatureBase64, // Signature ist Base64-Kodiert
             tPublicKey,          // öffentlicher Schlüssel
             tSignature           // Signatur
);

if (tErr = _ErrOK)
  WinDialogBox(0, 'Verifizierung', 'Die Signatur wurde verifiziert.', _WinIcoInformation, _WinDialogOk, 0);

// ...

Zusätzlich zu den Fehlerwerten, können beide Funktionen die Laufzeitfehler _ErrHdlInvalid, _ErrValueInvalid und _ErrValueRange auslösen.

6 Kommentare

6 Kommentare “Signieren mit CONZEPT 16”

  1. @gkoinzer
    Eine sogenannte Zertifizierungsstelle (certification authority) nimmt das Erstellen und die Ausgabe von digitalen Zertifikaten vor. Zertifikatsaussteller haben unterschiedliche Preismodelle. Die Kosten hängen von der Art des Zertifikats (Serverzertifikat, E-Mail-Signatur etc.), sowie von der Anzahl der benötigten Zertifikate ab.

  2. Bitte für den bezüglich Zertifikaten unwissenden Nutzer noch ein paar Hinweise über Zertifikate:
    – wo am besten ausstellen lassen
    – Kosten
    – was ist zu beachten bzw. wo liegen Risiken
    – wie sollte der Ablauf organisiert bzw. automatisiert werden

  3. @Kilian
    Für die Überprüfung älterer Signaturen ist MD5 auf jeden Fall notwendig, für die Generierung neuer Signaturen sollte es nach Möglichkeit nicht mehr verwendet werden. Leider läßt sich der Fall, das andere (ältere) Software-Anwendungen Signaturen mit MD5 erwarten, nicht zu 100% ausschließen, daher gibt es eben noch diese Option für MemSign().

  4. Vielen Dank für Ihre Rückmeldung.
    Die Erweiterung des kryptografischen Bereichs in CONZEPT 16 ist hiermit noch nicht abgeschlossen. Wünsche und Anregungen von unseren Softwarepartnern sind natürlich für zukünftige Erweiterungen gern gesehen.

  5. Super, das ist m. E. eine gute Erweiterung, die sicherlich sehr hilfreich sein wird, um das keineswegs einfache Thema der Authentizität und Integrität von Informationen in den eigenen Anwendungen in den Griff zu bekommen!

    Hier noch ein paar Anregungen:
    – die Verwendung von MD5 ist problematisch, da MD5 bewiesenermassen nicht kollisionssicher ist, klar kann man auf einen anderen Hash-Algorithmus ausweichen, aber m. E. sollte MD5 gar nicht erst angeboten werden
    – es ist super, dass es jetzt neben MemHash, und MemHMAC eine weitere kryptographische Funktion für Memory-Objekte gibt, was ich nach wie vor vermisse sind symmetrische Basisfunktionen wie AES und 3DES, also z.B. einen MemCrypt-Befehl mit entsprechenden Optionen _MemCryptAES128 usw.
    – ähnlich wie nun neu die highlevel-Funktion MemSign könnte es später im Bereich der symmetrischen Verschlüsselung neben Basis-Funktionen wie AES und 3DES ebenfalls highlevel Funktionen für die authentifizierte Verschlüsselung (GCM, CCM, EAX usw.) geben

Kommentar abgeben