Unterschiedliches gemeinsames Geheimnis, das beim Versuch, den Diffie-Hellman-Schlüsselaustausch zwischen Swift und C# z
Posted: 13 Jan 2025, 11:58
Ich versuche, Diffie Hellman Key Exchange zwischen meiner iOS-App (Swift) und meinem ASP.NET 8 Core-Webserver zum Laufen zu bringen, aber bei allem, was ich bisher versucht habe, sind die auf jeder Plattform abgeleiteten gemeinsamen Geheimnisse immer noch unterschiedlich.
Dinge, die ich versucht habe:
.NET 8-Code (verwendet System.Security.Cryptography):
Dinge, die ich versucht habe:
- Stellte sicher, dass der öffentliche Schlüssel von iOS gesendet wurde Übereinstimmung zwischen App und Webserver bei Empfang und Verarbeitung.
- Außerdem wurde sichergestellt, dass der vom Webserver an die iOS-App gesendete öffentliche Schlüssel beim Empfang und bei der Verarbeitung übereinstimmt.
- (Könnte falsch sein), aber ich habe sichergestellt, dass die Schlüsselformate übereinstimmen konsistent in beiden Umgebungen.
- iOS-App generiert ein neues Schlüsselpaar und sendet seinen öffentlichen Schlüssel an den Webserver
- Der Webserver leitet das gemeinsame Geheimnis ab und sendet seinen öffentlichen Schlüssel an die App zurück
- Die iOS-App leitet dann das gemeinsame Geheimnis mithilfe des Server-PK ab
Und diese abgeleiteten gemeinsamen Geheimnisse stimmen nicht überein
Code: Select all
class HandshakeHelper
{
// CreateKeyPairs: Generates a private-public key pair
static func createKeyPairs() -> [String]
{
let privateKey = P256.KeyAgreement.PrivateKey()
let privateKeyBase64 = privateKey.derRepresentation.base64EncodedString()
let publicKeyBase64 = privateKey.publicKey.derRepresentation.base64EncodedString() // DER-encoded (X.509 format)
return [privateKeyBase64, publicKeyBase64]
}
// DeriveSharedSecret: Derives a shared secret using our private key and the other party's public key
static func deriveSharedSecret(ourPrivateKeyBase64: String, receivedPublicKeyBase64: String) -> String?
{
guard let privateKeyData = Data(base64Encoded: ourPrivateKeyBase64),
let receivedPublicKeyData = Data(base64Encoded: receivedPublicKeyBase64) else
{
print("Invalid key data")
return nil
}
do
{
// Reconstruct our private key and the received public key
let privateKey = try P256.KeyAgreement.PrivateKey(derRepresentation: privateKeyData)
let receivedPublicKey = try P256.KeyAgreement.PublicKey(derRepresentation: receivedPublicKeyData) // DER-encoded
// Derive the shared secret
let sharedSecret = try privateKey.sharedSecretFromKeyAgreement(with: receivedPublicKey)
// Return the shared secret as a base64 string
return sharedSecret.withUnsafeBytes { Data($0).base64EncodedString() }
} catch
{
print("Error deriving shared secret: \(error)")
return nil
}
}
}
Code: Select all
public class HandshakeHelper
{
// CreateKeyPairs: Generates a private-public key pair
public static List CreateKeyPairs()
{
using var ecdh = ECDiffieHellman.Create(ECCurve.NamedCurves.nistP256);
var privateKey = Convert.ToBase64String(ecdh.ExportECPrivateKey()); // PKCS#8 format
var publicKey = Convert.ToBase64String(ecdh.ExportSubjectPublicKeyInfo()); // X.509 format
File.WriteAllText("ecdh_priv.key", privateKey);
File.WriteAllText("ecdh_pub.key", publicKey);
return new List { privateKey, publicKey };
}
// DeriveSharedSecret: Derives a shared secret using our private key and the other party's public key
public static string DeriveSharedSecret(string ourPrivateKeyBase64, string receivedPublicKeyBase64)
{
var privateKeyBytes = Convert.FromBase64String(ourPrivateKeyBase64);
var receivedPublicKeyBytes = Convert.FromBase64String(receivedPublicKeyBase64);
using var ecdh = ECDiffieHellman.Create(ECCurve.NamedCurves.nistP256);
ecdh.ImportECPrivateKey(privateKeyBytes, out _); // Import our private key
using var receivedPublicKey = ECDiffieHellman.Create();
receivedPublicKey.ImportSubjectPublicKeyInfo(receivedPublicKeyBytes, out _); // Import the received public key
// Derive the shared secret
var sharedSecret = ecdh.DeriveKeyMaterial(receivedPublicKey.PublicKey);
return Convert.ToBase64String(sharedSecret); // Return shared secret in Base64 format
}
}