public RpcAnswer(Combinator answer) { Success = answer.Name != "rpc_error"; if (Success) Combinator = answer; else Error = new RpcError(answer.Get<int>("error_code"), answer.Get<string>("error_message")); }
/// <summary> /// Обработка входного pq вектора /// </summary> /// <param name="result">req_DH_params</param> /// <returns></returns> private Combinator ProcessPqAnswer(Combinator result) { // Разложение PQ на сомножители var u = result.Get <byte[]>("pq"); var bu = new BigInteger(u); // Входные строки в BE BigInteger p = RhoPollard(bu); BigInteger q = bu / p; if (p > q) { BigInteger max = q; q = p; p = max; } // Генерация encrypted data // Сформируем запрос p_q_inner_data#83c95aec pq:string p:string q:string nonce:int128 server_nonce:int128 new_nonce:int256 = P_Q_inner_data var nonce = result.Get <BigInteger>("nonce"); var serverNonce = result.Get <BigInteger>("server_nonce"); _newNonce = BigInteger.GenerateRandom(256); byte[] beP = p.GetBytes(); // p в BE byte[] beQ = q.GetBytes(); // q в BE var pQInnerData = new Combinator("p_q_inner_data", u, beP, beQ, nonce, serverNonce, _newNonce); if (_nonce != nonce) { throw new ArgumentException("nonce ответа несовпадает"); } SHA1 sha = SHA1.Create(); byte[] data = pQInnerData.Serialize(); byte[] hash = sha.ComputeHash(data); byte[] dataWithHash; using (var ms = new MemoryStream()) using (var bw = new BinaryWriter(ms)) { bw.Write(hash); bw.Write(data); bw.Write(GenerateRandomBytes(255 - bw.BaseStream.Position)); dataWithHash = ms.ToArray(); } byte[] encryptedData = RSAEncrypt(dataWithHash); var fingerprint = result.Get <Combinator>("server_public_key_fingerprints").Get <long>(0); // HACK: отпечаток ключа return(new Combinator("req_DH_params", nonce, serverNonce, beP, beQ, fingerprint, encryptedData)); }
public RpcAnswer(Combinator answer) { Success = answer.Name != "rpc_error"; if (Success) { Combinator = answer; } else { Error = new RpcError(answer.Get <int>("error_code"), answer.Get <string>("error_message")); } }
private Combinator Unwrap(Combinator response, long responseId, long sessionId, string type) { switch (response.Name) { case "gzip_packed": byte[] packedData = response.Get <byte[]>("packed_data"); using (var gz = new GZipStream(new MemoryStream(packedData, 0, packedData.Length), CompressionMode.Decompress, false)) response = new Combinator(new BinaryReader(gz).ReadAllBytes(), type); return(Unwrap(response, responseId, sessionId, type)); case "rpc_result": if (responseId == sessionId) { // выполним распаковку ответа из Object // rpc_result#f35c6d01 req_msg_id:long result:Object = RpcResult; var raw = response.Get <byte[]>("result"); var combinator = new Combinator(raw, type); return(Unwrap(combinator, responseId, sessionId, type)); } Trace.TraceWarning("Unexpected session id: {0}. Actual: {1}. Combinator: {2}", responseId, sessionId, response); return(null); default: return(response); } }
/// <summary> /// Генерация клиентского запроса с параметрами Диффи-Хеллмана /// </summary> /// <param name="serverDh"></param> /// <returns></returns> private Combinator SetClientDhParams(Combinator serverDh) { var g = serverDh.Get <int>("g"); var dhPrime = serverDh.Get <byte[]>("dh_prime"); var gA = serverDh.Get <byte[]>("g_a"); var dh = new DiffieHellmanManaged(dhPrime, new BigInteger(g).GetBytes(), 2048); // generate the public key of the second DH instance byte[] gB = dh.CreateKeyExchange(); // let the second DH instance compute the shared secret using the first DH public key _authKey = dh.DecryptKeyExchange(gA); // Сформируем ответ // отдаем g_b в BE var clientDhInnerData = new Combinator("client_DH_inner_data", _nonce, _serverNonce, (long)0, gB); byte[] s = clientDhInnerData.Serialize(); // Шифрование строки var aes = new Aes256IgeManaged(CalculateTmpAesKey(_newNonce, _serverNonce) , CalculateTmpAesIV(_newNonce, _serverNonce)); using (var ms = new MemoryStream()) using (var bw = new BinaryWriter(ms)) { SHA1 sha1 = SHA1.Create(); bw.Write(sha1.ComputeHash(s)); bw.Write(s); var r = new Random(); while (bw.BaseStream.Length % 16 != 0) { bw.Write((byte)r.Next()); } s = aes.Encrypt(ms.ToArray()); } // Сформируем ответ var setClientDhParams = new Combinator("set_client_DH_params", _nonce, _serverNonce, s); return(setClientDhParams); }
/// <summary> /// Обработка DH параметров /// </summary> /// <param name="dhparams"></param> /// <returns></returns> private Combinator ProcessDhParams(Combinator dhparams) { var ea = dhparams.Get <byte[]>("encrypted_answer"); // Обновим server nonce _serverNonce = dhparams.Get <BigInteger>("server_nonce"); // Расшифровка строки var aes = new Aes256IgeManaged(CalculateTmpAesKey(_newNonce, _serverNonce), CalculateTmpAesIV(_newNonce, _serverNonce)); byte[] answerWithHash = aes.Decrypt(ea); if (answerWithHash.Length % 16 != 0) { throw new ArgumentException("Неверный ответ внутри сообщения"); } byte[] answer = answerWithHash.Skip(20).ToArray(); return(new Combinator(answer, "Server_DH_inner_data")); }
private void UpdateDifference() { // updates.getDifference#5b36855a pts:int date:int = updates.Difference; RpcAnswer result = RpcCall(new Combinator("updates.getDifference", _updatingState.Pts, _updatingState.Date, _updatingState.Qts)); // updates.differenceEmpty#5d75a138 date:int seq:int = updates.Difference; // updates.difference#8adb0077 new_messages:Vector<Message> other_updates:Vector<Update> chats:Vector<Chat> users:Vector<User> state:updates.State = updates.Difference; // updates.differenceSlice#c5e839b4 new_messages:Vector<Message> other_updates:Vector<Update> chats:Vector<Chat> users:Vector<User> intermediate_state:updates.State = updates.Difference; if (result.Success) { Combinator c = result.Combinator; switch (c.Name) { case "updates.differenceEmpty": _updatingState.Update(c); return; case "updates.difference": _updatingState.Update(c.Get <Combinator>("state")); break; case "updates.differenceSlice": _updatingState.Update(c.Get <Combinator>("intermediate_state")); break; default: throw new ArgumentOutOfRangeException(c.Name); } Difference(c.Get <Combinator>("new_messages")); Difference(c.Get <Combinator>("other_updates")); Difference(c.Get <Combinator>("chats")); Difference(c.Get <Combinator>("users")); } else { throw new Exception(result.Error.ToString()); } }
private Combinator Unwrap(Combinator response, long responseId, long sessionId, string type) { switch (response.Name) { case "gzip_packed": byte[] packedData = response.Get<byte[]>("packed_data"); using (var gz = new GZipStream(new MemoryStream(packedData, 0, packedData.Length), CompressionMode.Decompress, false)) response = new Combinator(new BinaryReader(gz).ReadAllBytes(), type); return Unwrap(response, responseId, sessionId, type); case "rpc_result": if (responseId == sessionId) { // выполним распаковку ответа из Object // rpc_result#f35c6d01 req_msg_id:long result:Object = RpcResult; var raw = response.Get<byte[]>("result"); var combinator = new Combinator(raw, type); return Unwrap(combinator, responseId, sessionId, type); } Trace.TraceWarning("Unexpected session id: {0}. Actual: {1}. Combinator: {2}", responseId, sessionId, response); return null; default: return response; } }
/// <summary> /// Обработка входного pq вектора /// </summary> /// <param name="result">req_DH_params</param> /// <returns></returns> private Combinator ProcessPqAnswer(Combinator result) { // Разложение PQ на сомножители var u = result.Get<byte[]>("pq"); var bu = new BigInteger(u); // Входные строки в BE BigInteger p = RhoPollard(bu); BigInteger q = bu / p; if (p > q) { BigInteger max = q; q = p; p = max; } // Генерация encrypted data // Сформируем запрос p_q_inner_data#83c95aec pq:string p:string q:string nonce:int128 server_nonce:int128 new_nonce:int256 = P_Q_inner_data var nonce = result.Get<BigInteger>("nonce"); var serverNonce = result.Get<BigInteger>("server_nonce"); _newNonce = BigInteger.GenerateRandom(256); byte[] beP = p.GetBytes(); // p в BE byte[] beQ = q.GetBytes(); // q в BE var pQInnerData = new Combinator("p_q_inner_data", u, beP, beQ, nonce, serverNonce, _newNonce); if (_nonce != nonce) throw new ArgumentException("nonce ответа несовпадает"); SHA1 sha = SHA1.Create(); byte[] data = pQInnerData.Serialize(); byte[] hash = sha.ComputeHash(data); byte[] dataWithHash; using (var ms = new MemoryStream()) using (var bw = new BinaryWriter(ms)) { bw.Write(hash); bw.Write(data); bw.Write(GenerateRandomBytes(255 - bw.BaseStream.Position)); dataWithHash = ms.ToArray(); } byte[] encryptedData = RSAEncrypt(dataWithHash); var fingerprint = result.Get<Combinator>("server_public_key_fingerprints").Get<long>(0); // HACK: отпечаток ключа return new Combinator("req_DH_params", nonce, serverNonce, beP, beQ, fingerprint, encryptedData); }
/// <summary> /// Обработка DH параметров /// </summary> /// <param name="dhparams"></param> /// <returns></returns> private Combinator ProcessDhParams(Combinator dhparams) { var ea = dhparams.Get<byte[]>("encrypted_answer"); // Обновим server nonce _serverNonce = dhparams.Get<BigInteger>("server_nonce"); // Расшифровка строки var aes = new Aes256IgeManaged(CalculateTmpAesKey(_newNonce, _serverNonce), CalculateTmpAesIV(_newNonce, _serverNonce)); byte[] answerWithHash = aes.Decrypt(ea); if (answerWithHash.Length % 16 != 0) throw new ArgumentException("Неверный ответ внутри сообщения"); byte[] answer = answerWithHash.Skip(20).ToArray(); return new Combinator(answer, "Server_DH_inner_data"); }
/// <summary> /// Генерация клиентского запроса с параметрами Диффи-Хеллмана /// </summary> /// <param name="serverDh"></param> /// <returns></returns> private Combinator SetClientDhParams(Combinator serverDh) { var g = serverDh.Get<int>("g"); var dhPrime = serverDh.Get<byte[]>("dh_prime"); var gA = serverDh.Get<byte[]>("g_a"); var dh = new DiffieHellmanManaged(dhPrime, new BigInteger(g).GetBytes(), 2048); // generate the public key of the second DH instance byte[] gB = dh.CreateKeyExchange(); // let the second DH instance compute the shared secret using the first DH public key _authKey = dh.DecryptKeyExchange(gA); // Сформируем ответ // отдаем g_b в BE var clientDhInnerData = new Combinator("client_DH_inner_data", _nonce, _serverNonce, (long)0, gB); byte[] s = clientDhInnerData.Serialize(); // Шифрование строки var aes = new Aes256IgeManaged(CalculateTmpAesKey(_newNonce, _serverNonce) , CalculateTmpAesIV(_newNonce, _serverNonce)); using (var ms = new MemoryStream()) using (var bw = new BinaryWriter(ms)) { SHA1 sha1 = SHA1.Create(); bw.Write(sha1.ComputeHash(s)); bw.Write(s); var r = new Random(); while (bw.BaseStream.Length % 16 != 0) bw.Write((byte)r.Next()); s = aes.Encrypt(ms.ToArray()); } // Сформируем ответ var setClientDhParams = new Combinator("set_client_DH_params", _nonce, _serverNonce, s); return setClientDhParams; }