2017-05-16 5 views
2

Ich versuche, Pdf-Dokumente unter Verwendung Pkcs11Interop. Net-Bibliothek zu unterzeichnen. Ich brauche ECDSA-Verschlüsselung Algorithmus mit SHA256 Hash-Algorithmus. Und ich verwende SoftHSM 2.2.0 zum Speichern privater Schlüssel.Signing PDF von Pkcs11Interop für CKM_ECDSA_SHA256 mit SoftHSM 2.2.0 (ECDSA mit SHA256) C# .net

Ich fand eine CKM enum, CKM_ECDSA_SHA256, die ich beim Erstellen eines Objekts der Klassenmechanismus für den Aufruf der Sign-Methode der Sitzung übergeben.

Ich bekomme die Antwort von der "Signdata" -Methode, jedoch beim Öffnen der Pdf-Dateien erzeugt nach der Unterzeichnung geben Sie einen Fehler "Signatur ungültig". Hier ist das Code-Snippet für den Signdata-Methodenaufruf. Ich bekomme keinen Fehler oder eine Ausnahme im Code, aber die pdf, wie ich erwähnt habe, zeigen die Unterschrift ungültig.

private Pkcs11 _pkcs11; 
private Slot _slot; 
private Session _session; 

try 
{ 
    _pkcs11 = new Pkcs11(hsmCryptoApi, true); 
} 
catch (Pkcs11Exception ex) 
{ 
    if (ex.RV == CKR.CKR_CANT_LOCK) 
     _pkcs11 = new Pkcs11(hsmCryptoApi, false); 
    else 
     throw ex; 
} 

_slot = FindSlot(_pkcs11, _certificateInformation.TokenLabel); 
_session = _slot.OpenSession(true); 

using (Mechanism mechanism = new Mechanism(CKM.CKM_ECDSA_SHA256)) 
{ 
    _session.Login(CKU.CKU_USER, passowrd); 
    byte[] signedHash = _session.Sign(mechanism, GetPrivateKeyHandle(), message); 
    _session.Logout(); 
    return signedHash; 
} 

private ObjectHandle GetPrivateKeyHandle() 
{ 
    string keyLabel = _certificateInformation.KeyLabel; 
    List<ObjectAttribute> searchTemplate = new List<ObjectAttribute>(); 
    searchTemplate.Add(new ObjectAttribute(CKA.CKA_CLASS, CKO.CKO_PRIVATE_KEY)); 
    searchTemplate.Add(new ObjectAttribute(CKA.CKA_LABEL, keyLabel)); 
    List<ObjectHandle> foundObjects = _session.FindAllObjects(searchTemplate); 
    return foundObjects[0]; 
} 
  • Bitte sagen Sie mir, wenn SoftHSM 2.2.0 ECDSA_P256 unterstützt mit SHA256 oder nicht ??
  • Wenn nicht, gibt es eine Möglichkeit, die Unterstützung zu aktivieren?
  • Wenn es unterstützt, bitte helfen Sie mir, wie das zu beheben?
  • Es sieht aus wie es mir will ECDSA_Param passieren, hat jemand einen Code-Schnipsel für die ECDSA_Param
+0

Ich sehe keine offensichtliche Problem im Code haben Sie auf dem Laufenden, so ist meine Vermutung, dass Ihr Problem könnte durch einen anderen Code in Ihre Lösung wie PDF-Verarbeitung verursacht werden , CMS Struktur Gebäude etc. – jariq

Antwort

0

Ich denke, vorbei Sie ECDSA-Sig-Value Struktur und füllen Sie ihn mit den Daten aus Ihrem signedHash Variable konstruieren müssen.

PKCS#11 v2.20 Kapitel 12.3.1:

Für die Zwecke dieser Mechanismen ein ECDSA Signatur ist ein Oktett Kette von gleicher Länge, die höchstens zwei Mal nLen Oktetts ist, wo nLen ist die Länge in Oktette der Basispunktreihenfolge n. Die Signatur Octets entsprechen der Verkettung der ECDSA-Werte r und s, , beide dargestellt als eine Oktettskette gleicher Länge von höchstens nLen mit dem höchstwertigen Byte zuerst. Wenn r und s eine unterschiedliche Oktett Länge haben, muss die kürzere von beiden mit führenden Null-Oktetts aufgefüllt werden, so dass beide die gleiche Oktettlänge haben. Lose gesprochen, die erste Hälfte der Signatur ist r und die zweite Hälfte ist s. Bei Signaturen , die mit einem Token erstellt wurden, hat die resultierende Signatur immer die Länge 2nLen. Für Signaturen, die an einen Token zur Verifizierung übergeben werden, darf die Signatur eine kürzere Länge haben, muss aber wie zuvor angegeben zusammengesetzt sein.

RFC5753 Kapitel 7.2:

Bei Verwendung von ECDSA mit SignedData, verwenden ECDSA Signaturen codiert vom Typ:

ECDSA-Sig-Value ::= SEQUENCE { 
    r INTEGER, 
    s INTEGER } 

ECDSA-Sig-Wert wird in [PKI-ALG angegebenen ].Innerhalb CMS, ECDSA-Sig-Wert ist DER-codiert und in einem Signaturfeld von SignedData platziert.

folgende Methode verwendet BouncyCastle Bibliothek DER-codierte ECDSA-Sig-Value Struktur konstruiert:

public static byte[] ConstructEcdsaSigValue(byte[] rs) 
{ 
    if (rs == null) 
     throw new ArgumentNullException(nameof(rs)); 

    if (rs.Length < 2 || rs.Length % 2 != 0) 
     throw new ArgumentException("Invalid length", nameof(rs)); 

    int halfLen = rs.Length/2; 

    byte[] half1 = new byte[halfLen]; 
    Array.Copy(rs, 0, half1, 0, halfLen); 
    var r = new Org.BouncyCastle.Math.BigInteger(1, half1); 

    byte[] half2 = new byte[halfLen]; 
    Array.Copy(rs, halfLen, half2, 0, halfLen); 
    var s = new Org.BouncyCastle.Math.BigInteger(1, half2); 

    var derSequence = new Org.BouncyCastle.Asn1.DerSequence(
     new Org.BouncyCastle.Asn1.DerInteger(r), 
     new Org.BouncyCastle.Asn1.DerInteger(s)); 

    return derSequence.GetDerEncoded(); 
} 
+0

Vielen Dank @jariq für Ihre Antwort. Ich bin mir jedoch nicht sicher, wie ECDSA-Sig-Wert zu verwenden ist. Wenn Sie ein Code-Snippet diesbezüglich haben, wird das für mich sehr hilfreich sein. Ich bin wirklich an diesem Punkt fest, ich schätze jede Hilfe. Danke im Voraus. – Kumar

+0

@Kumar Leider habe ich momentan kein fertiges Code-Sample zur Verfügung, aber ich werde versuchen, es bis Ende dieser Woche zu erstellen. – jariq

+0

Vielen Dank @Jariq dafür. Es ist wirklich sehr hilfreich. Ich muss nur wissen, ist die signedHash-Variable meiner Eingabe die Eingabe für diese Methode und es wäre der endgültige und korrekte Wert der signedHash-Variable? Muss ich etwas wie unten schreiben ........................................ ........................ return (ConstructEcdsaSigValue (signedHash)); – Kumar

0

Ich dachte, die Lösung zu teilen, die für mich gearbeitet. In dem obigen Codeausschnitt erwähnt habe ich die folgenden Dinge:

using (Mechanism mechanism = new Mechanism(CKM.CKM_ECDSA)) 
     { 
      _session.Login(CKU.CKU_USER, passowrd); 
      byte[] signedHash = _session.Sign(mechanism, GetPrivateKeyHandle(), GetMessageDigest(message)); 
      _session.Logout(); 
      return ConstructEcdsaSigValue(signedHash); 
     } 

    private byte[] GetMessageDigest(byte[] message) 
    { 
     using (Mechanism mechanism = new Mechanism(CKM_SHA256)) 
     { 
     return _session.Digest(mechanism, message); 
     } 
    } 

    public static byte[] ConstructEcdsaSigValue(byte[] rs) 
    { 
     if (rs == null) 
      throw new ArgumentNullException(nameof(rs)); 

     if (rs.Length < 2 || rs.Length % 2 != 0) 
      throw new ArgumentException("Invalid length", nameof(rs)); 

     int halfLen = rs.Length/2; 

     byte[] half1 = new byte[halfLen]; 
     Array.Copy(rs, 0, half1, 0, halfLen); 
     var r = new Org.BouncyCastle.Math.BigInteger(1, half1); 

     byte[] half2 = new byte[halfLen]; 
     Array.Copy(rs, halfLen, half2, 0, halfLen); 
     var s = new Org.BouncyCastle.Math.BigInteger(1, half2); 

     var derSequence = new Org.BouncyCastle.Asn1.DerSequence(
      new Org.BouncyCastle.Asn1.DerInteger(r), 
      new Org.BouncyCastle.Asn1.DerInteger(s)); 

     return derSequence.GetDerEncoded(); 
    }