public bool GetServerIdentity(byte[] clientProofOfWork, out byte[] serverIdentity) { serverIdentity = null; if (!ClientProofOfWork.Parse(clientProofOfWork, out ClientProofOfWork cpow)) { return(false); } if (!cpow.knownSecretariumPubKey.SequenceEqual(GenesisPubKey)) { return(false); } // Create ephemereal DH keys var eph = ECDHHelper.CreateCngKey(); var ephCng = ECDHHelper.CreateECDiffieHellmanCngSha256(eph); var ephPubKey = ephCng.PublicKey(); // Get CommonKey from DH var clientPublicCngKey = Session.ClientEphDHPubKey.ToECDHCngKey(); var commonKey = ephCng.DeriveKeyMaterial(clientPublicCngKey); // Generate a random SymmetricKey var symmetricKey = ByteHelper.GetRandom(commonKey.Length); // XOR CommonKey and SymmetricKey to produce a PreMasterSecret var preMasterSecret = commonKey.Xor(symmetricKey); serverIdentity = ByteHelper.Combine(preMasterSecret, ephPubKey, GenesisPubKey); Session.SymmetricKey = symmetricKey; return(true); }
private bool FullProtocolFromX509(ScpConfig.EncryptionMode encryptionMode, out byte[] symmetricKey, out MockedSecretarium secretarium) { // Client keys Assert.IsTrue(ScpConfigHelper.TryLoad("test.x509.json", out ScpConfig config)); Assert.IsTrue(config.TryGetECDsaKey(out ECDsaCng clientECDsaKeyCng, "SecretariumTestClient256")); var clientPub = clientECDsaKeyCng.ExportPublicKeyRaw(); // Client Hello var clientEph = ECDHHelper.CreateCngKey(); var clientEphCng = ECDHHelper.CreateECDiffieHellmanCngSha256(clientEph); var clientEphPub = clientEphCng.PublicKey(); var clientHello = clientEphPub; Assert.IsTrue(ClientHello.Parse(clientHello, out ClientHello clientHelloObj)); // Server Hello secretarium = new MockedSecretarium(encryptionMode); secretarium.GetServerHello(clientHello, out byte[] serverHello); Assert.IsTrue(ServerHello.Parse(serverHello, 18, out ServerHello serverHelloObj)); // Client ClientProofOfWork Assert.IsTrue(DiffieHellmanHelper.ComputeProofOfWork(serverHelloObj.proofOfWorkDetails, out byte[] proofOfWork)); var clientProofOfWork = ByteHelper.Combine(proofOfWork.ExtendTo(32), MockedSecretarium.GenesisPubKey); Assert.IsTrue(ClientProofOfWork.Parse(clientProofOfWork, out ClientProofOfWork clientProofOfWorkObj)); // Server Identity secretarium.GetServerIdentity(clientProofOfWork, out byte[] serverIdentity); Assert.IsTrue(ServerIdentity.Parse(serverIdentity, out ServerIdentity serverIdentityObj)); // Client computes symmetric key symmetricKey = DiffieHellmanHelper.GetSymmetricKey( clientEphCng, serverIdentityObj.ephDHKey, serverIdentityObj.preMasterSecret); // Client Proof Of Identity var nonce = ByteHelper.GetRandom(32); var nonceSigned = clientECDsaKeyCng.SignData(nonce); var clientProofOfIdentity = ByteHelper.Combine(nonce, clientEphPub, clientPub, nonceSigned); Assert.IsTrue(ClientProofOfIdentity.Parse(clientProofOfIdentity, out ClientProofOfIdentity clientProofOfIdentityObj)); // Client Encrypts Client Proof Of Identity var ivOffset = ByteHelper.GetRandom(16); var encryptedClientProofOfIdentity = encryptionMode == ScpConfig.EncryptionMode.AESCTR ? clientProofOfIdentity.AesCtrEncrypt(symmetricKey, ivOffset) : clientProofOfIdentity.AesGcmEncryptWithOffset(symmetricKey, ivOffset); var encryptedClientProofOfIdentityWithIvOffset = ByteHelper.Combine(ivOffset, encryptedClientProofOfIdentity); // Server Checks And Sends Proof Of Identity Assert.IsTrue(secretarium.GetServerProofOfIdentity( encryptedClientProofOfIdentityWithIvOffset, out byte[] encryptedServerProofOfIdentity)); // Client Decrypts Server Proof Of Identity ivOffset = encryptedServerProofOfIdentity.Extract(0, 16); var serverProofOfIdentity = encryptionMode == ScpConfig.EncryptionMode.AESCTR ? encryptedServerProofOfIdentity.Extract(16).AesCtrDecrypt(symmetricKey, ivOffset) : encryptedServerProofOfIdentity.Extract(16).AesGcmDecryptWithOffset(symmetricKey, ivOffset); Assert.IsTrue(ServerProofOfIdentity.Parse(serverProofOfIdentity, out ServerProofOfIdentity serverProofOfIdentityObj)); // Client Checks Server Proof Of Idendity var msg = "Hey you! Welcome to Secretarium!".ToBytes(); var secretariumECDsaCng = ECDsaHelper.ImportPublicKey(serverIdentityObj.publicKey); Assert.IsTrue(secretariumECDsaCng.VerifyData( ByteHelper.Combine(serverProofOfIdentityObj.nonce, msg), serverProofOfIdentityObj.welcomeSigned)); return(true); }