-
-
Save below/4ac77dbf03a61fbc69bbcb3e7bebe011 to your computer and use it in GitHub Desktop.
Diffie-Hellman-Keyexchange
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import CryptoKit | |
import Foundation | |
/** # Diffie-Heelman Keyexchange | |
This playground is meant to test a Diffie-Hellman Key Exchange between .Net´s `System.Security.Cryptography` and `CryptoKit`. Currently, my test is failing and any help is appreciated. More comments are in the code | |
*/ | |
/// For testing, this is a constant private key. Yes, all of these keys have been generated for testing and are not used in production | |
let clientPrivateKey = try P521.KeyAgreement.PrivateKey(rawRepresentation: Data(base64Encoded: "AQmPwAfFwDDN298ek1vH3YIslW4hT2qPps7X4A2TMtnEBdJ6owPwB8cidtr9bl6vRiqIFJAc87S7lHwEbHoZCdRK")!) | |
let clientPublicKey = clientPrivateKey.publicKey | |
/// This is the public key we received from the server. **NOTE:** it is in the `eccBlob` Format, which means it starts with `ECK5`, and four bytes designating the length, followed by the actual key. For CryptoKit, the first 8 bytes must be discarded | |
let serverPublicKeyRaw = Data(base64Encoded: "RUNLNUIAAAABKtzFNMpPFNikLBlbkAkqo8c9Y8uXES3nNfDA50iq6TqpNgNvv6Ly/UC9/kH5ttP22qwN4A/axG4oqqfLhPP5vm0BDTTJh5FkfzaC0aHkqrBB5SznodNaD02UIqwCFjVsQiMtvl4q8OYCi41i3pRfD8MzpbUB1eQKow9EmQrTVmGm59k=")![8...] | |
var serverPublicKey: P521.KeyAgreement.PublicKey! | |
do { | |
serverPublicKey = try P521.KeyAgreement.PublicKey(rawRepresentation: serverPublicKeyRaw) | |
} catch { | |
print ("Server Public Key does not work: \(error)") | |
} | |
/// Now lets create a shared Secret | |
let sharedSecret = try clientPrivateKey.sharedSecretFromKeyAgreement( | |
with: serverPublicKey) | |
/// and derive a `SymetricKey` | |
let sharedHash = SHA256.self | |
let sharedInfo = serverPublicKey.rawRepresentation | |
let sharedLength = 32 | |
let symetricKey = sharedSecret.x963DerivedSymmetricKey( | |
using: sharedHash, | |
sharedInfo: Data(), | |
outputByteCount: sharedLength) | |
/// (I have also tried `hkdfDerivedSymmetricKey`, no change) | |
/// Let's encrypt some stuff with it: | |
let data = "Hello, World!".data(using: .utf8)! | |
let sealedBox = try AES.GCM.seal(data, using: symetricKey) | |
/** Now, for testing, this is the raw sharedSecret I received from the server after sending the above PublicKey. It has been created using: | |
`ECDiffieHellmanCng.DeriveKeyMaterial(clientCngKey)`, a more detailed description is here: https://learn.microsoft.com/en-us/dotnet/api/system.security.cryptography.ecdiffiehellmancng?view=net-7.0 | |
*/ | |
let sharedServerSecret = Data(base64Encoded: "l0w86tNivCCin6dPxr/T6rIJsx1EZvrQZlFSGL2PIDQ=".data(using: .utf8)!)! | |
/// We can successfully create a `SymetricKey` with this data | |
let serverSymetricKey = SymmetricKey(data: sharedServerSecret) | |
/// Finally, let's try to open the box with the serverSymetricKey, as the assumption is that this is precisely what the server will attempt to do. After all, the keys *should* be identical: | |
do { | |
let openBox = try AES.GCM.open(sealedBox, using: serverSymetricKey) | |
String(data: openBox, encoding: .utf8) | |
} catch { | |
/// And we land here :( "Error opening box: authenticationFailure\n" | |
print ("Error opening box: \(error)") | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment