2017-05-15 5 views
0

Ich versuche eine C# -Implementierung zu erstellen, um Pushes an Apple über ihren HTTP/2 APNS-Endpunkt mit .Net-Core in Docker zu senden. Ein Teil davon erfordert das Senden eines verschlüsselten JWT-Autorisierungs-Tokens zusammen mit der Nutzlast. Mit .Net-Core kann ich das Token signieren, wenn es unter Windows läuft, aber wenn es im Linux-Docker-Image ausgeführt wird, gibt es einen Tipp über das Laden des Schlüssels.ECDsa Anmelden .Net Core unter Linux

Wenn ich in .net Core Docker Image ausgeführt wird, erhalte ich eine platformnotsupported Exception beim Laden des Schlüssels.

public static string SignES256(string privateKey, string header, string payload) 
    { 

     // This is the failing Call 
     CngKey key = CngKey.Import(Convert.FromBase64String(privateKey), CngKeyBlobFormat.Pkcs8PrivateBlob); 

     using (ECDsaCng dsa = new ECDsaCng(key)) 
     { 
      var unsignedJwtData = 
       System.Convert.ToBase64String(Encoding.UTF8.GetBytes(header)) + "." + System.Convert.ToBase64String(Encoding.UTF8.GetBytes(payload)); 
      var unsignedJwtDataBytes = Encoding.UTF8.GetBytes(unsignedJwtData); 

      var signature = 
       dsa.SignData(unsignedJwtDataBytes, 0, unsignedJwtDataBytes.Length, HashAlgorithmName.SHA256); 
      return unsignedJwtData + "." + System.Convert.ToBase64String(signature); 
     } 
    } 

Wie kann ich dies von .NET Core unter Linux tun?

Danke.

Antwort

1

ECDsaCng ist eine ECDSA-Implementierung mit Windows CNG. Es ist spezifisch für Windows, also nicht unter Linux unterstützt. nicht die einfachste Sache der Welt

Der Cross-Plattform-Weg, dies ist

using (ECDsa ecdsa = ECDsa.Create()) 
{ 
    ecdsa.ImportParameters(Pkcs8ToParameters(privateKey)); 

    // the stuff in your current using 
} 

Natürlich PKCS # 8 bis ECParameters wäre zu tun. Aber wir können es versuchen. In another answer gibt es eine Aufschlüsselung der Erstellung eines PKCS # 8 für RSA.

Lassen Sie uns diesen Blob nehmen:

308187020100301306072A8648CE3D020106082A8648CE3D030107046D306B02 
0101042070A12C2DB16845ED56FF68CFC21A472B3F04D7D6851BF6349F2D7D5B 
3452B38AA144034200048101ECE47464A6EAD70CF69A6E2BD3D88691A3262D22 
CBA4F7635EAFF26680A8D8A12BA61D599235F67D9CB4D58F1783D3CA43E78F0A 
5ABAA624079936C0C3A9 

Es bricht wie

30 /* SEQUENCE */ 
    81 87 (payload is 0x87 bytes) 

    02 /* INTEGER */ 01 (1 byte) 00 // Integer: 0. // validate this 

    30 /* SEQUENCE */ 13 (0x13 bytes) 

     06 /* OBJECT IDENTIFIER */ 07 (7 bytes) 
     2A8648CE3D0201 (1.2.840.10045.2.1/ecPublicKey) // validate this 

     06 /* OBJECT IDENTIFIER */ 08 (8 bytes) 
     2A8648CE3D030107 (1.2.840.10045.3.1.7/secp256r1) // save this, curveName 

    04 /* OCTET STREAM (byte[]) */ 6D (0x6D bytes) 
     // Since the constructed (0x20) bit isn't set in the tag normally we stop here, 
     // but we know from the ecPublicKey context that this is also DER data. 

     30 /* SEQUENCE */ 6B (0x6B bytes) 

     02 /* Integer */ 01 (1 byte) 01 // Integer: 1. // validate this. 

     04 /* OCTET STREAM (byte[]) */ 20 (0x20 bytes/256 bits) 
      70A12C2DB16845ED56FF68CFC21A472B3F04D7D6851BF6349F2D7D5B3452B38A // save this: D 

     A1 /* CONSTRUCTED CONTEXT SPECIFIC 1 */ 44 (0x44 bytes) 

      03 /* BIT STRING (byte[] if the first byte is 0x00) */ 66 (0x66 bytes) 

       00 // Oh, good, it's a normal byte[]. Validate this. 

       // Formatting will become apparent. Save this. 
       04 
       8101ECE47464A6EAD70CF69A6E2BD3D88691A3262D22CBA4F7635EAFF26680A8 
       D8A12BA61D599235F67D9CB4D58F1783D3CA43E78F0A5ABAA624079936C0C3A9 

Der BITKETTE am Ende ist "der öffentliche Schlüssel". Da es mit 04 beginnt (was es normalerweise tut, es sei denn, der Absender ist sauer auf Sie), stellt es einen "unkomprimierten Punkt" dar, was bedeutet, dass die erste Hälfte dessen, was übrig ist, die X-Koordinate ist und der Rest die Y-Koordinate ist. Also von dieser Struktur könnten Sie so etwas wie

string curveOid; 

// You can decode the OID, or special case it. 
switch (curveName) 
{ 
    case "2A8648CE3D030107": 
     // secp256r1 
     curveOid = "1.2.840.10045.3.1.7"; 
     break; 
    case "2B81040022" 
     // secp384r1 
     curveOid = "1.3.132.0.34"; 
     break; 
    case "2B81040023": 
     // secp521r1 
     curveOid = "1.3.132.0.35"; 
     break; 
    default: 
     throw new InvalidOperationException(); 
} 

return new ECParameters 
{ 
    Curve = ECCurve.CreateFromValid(curveOid), 

    // We saved this. 
    D = d, 

    Q = new ECPoint 
    { 
     X = x, 
     Y = y 
    }, 
} 

bekommen Dies geschieht, der Schlüssel in Abschnitt D.1 (NIST P-256/secp256r1) von Suite B Implementer’s Guide to FIPS 186-3 (ECDSA) verwendet werden.

Da das EC-Schlüsselformat auf INTEGER-Werten gnädigerweise knapp ist (was Padding-Bytes erfordern kann), können Sie einen manuellen Extraktor für jede Keysize erstellen, die Sie unterstützen möchten. Oder Sie können die DER-Leseroute live erleben. Oder Sie können versuchen, Ihren privaten Schlüssel in einer freundlicheren Form für Ihre Anwendung zu serialisieren.

Verwandte Themen