public void TrustContact(int contactId) { Pull(); Log("Sending TRUST_CONTACT command."); TextEncoder.SendCommand(stream, ConnectionCommand.TRUST_CONTACT); TextEncoder.SendInt(stream, contactId); using (Context context = new Context(config)) { var contact = context.Contacts .Where(u => u.PublicId == contactId) .SingleOrDefault(); contact.Trusted = 1; context.SaveChanges(); if (contact.SendAesKey == null) { AESPassword password = AESPassword.GenerateAESPassword(); JAESKey key = new JAESKey(contactId, password); PushOperations.SendIJType(context, key, UserId, UserId); X509Certificate2 cert = X509Certificate2Utils.ImportFromPem( context.Contacts .Where(u => u.PublicId == contactId) .Select(u => u.PublicCertificate) .SingleOrDefault()); BinaryEncoder.SendBytes(stream, RSAEncoder.Encrypt(password.Password, cert)); context.SaveChanges(); } } Push(); }
public void Connect(String password = null) { lock (mutex) { client = new TcpClient(serverAddress, ServerPort); logger.Log(this, "Client connected."); stream = new SslStream(client.GetStream(), false, verificator.AppCertificateValidation); X509CertificateCollection clientCertificates = new X509CertificateCollection(); clientCertificates.Add(MyCertificate); stream.AuthenticateAsClient("Dummy", clientCertificates, SslProtocols.Tls12, false); logger.Log(this, "SSL authentication completed."); logger.Log(this, "Handshake started."); var handshake = Handshake.Login(logger, stream, MyCertificate, password, UserName, ClientId); logger.Log(this, "Handshake successeded."); UserName = handshake.UserName; UserId = handshake.UserId; ClientId = handshake.ClientId; SelfAesPassword = handshake.SelfAesPassword; logger.Log(this, $"User {UserName} has id {UserId}. Client has id {ClientId}."); isConnected = true; } }
public static IJType GetJsonDecoded(Context context, byte[] message, long senderId) { byte[] aesBinKey = context.Contacts .Where(u => u.PublicId == senderId) .Select(u => u.ReceiveAesKey) .SingleOrDefault(); AESPassword key = new AESPassword(aesBinKey); byte[] decrypted = key.Decrypt(message); JsonTypes type = (JsonTypes)decrypted[0]; string jsonText = Encoding.UTF8.GetString(decrypted, 1, decrypted.Length - 1); switch (type) { case JsonTypes.ALARM: return(JsonConvert.DeserializeObject <JAlarm>(jsonText)); case JsonTypes.CONTACT_DETAIL: return(JsonConvert.DeserializeObject <JContactDetail>(jsonText)); case JsonTypes.MESSAGES: return(JsonConvert.DeserializeObject <JMessage>(jsonText)); case JsonTypes.MESSAGES_THREAD: return(JsonConvert.DeserializeObject <JMessageThread>(jsonText)); case JsonTypes.AES_KEY: return(JsonConvert.DeserializeObject <JAESKey>(jsonText)); default: throw new Exception("Unknown JsonType."); } }
public static byte[] GetJsonEncoded(Context context, IJType message, long receiverId, byte[] attechment = null) { byte[] aesBinKey = context.Contacts .Where(u => u.PublicId == receiverId) .Select(u => u.SendAesKey) .SingleOrDefault(); AESPassword key = new AESPassword(aesBinKey); MemoryStream stream = new MemoryStream(); BinaryEncoder.SendInt(stream, (int)message.GetJsonType()); string json = JsonConvert.SerializeObject(message); TextEncoder.SendString(stream, json); if (attechment == null) { BinaryEncoder.SendInt(stream, 0); } else { BinaryEncoder.SendInt(stream, 1); BinaryEncoder.SendBytes(stream, attechment); } byte[] notEncrypted = stream.ToArray(); return(key.Encrypt(notEncrypted)); }
public static JsonCapsula GetJsonDecoded(Context context, byte[] message, long senderId) { byte[] aesBinKey = context.Contacts .Where(u => u.PublicId == senderId) .Select(u => u.ReceiveAesKey) .SingleOrDefault(); AESPassword key = new AESPassword(aesBinKey); byte[] decrypted = key.Decrypt(message); MemoryStream stream = new MemoryStream(decrypted); JsonTypes type = (JsonTypes)BinaryEncoder.ReadInt(stream); string jsonText = TextEncoder.ReadString(stream); byte[] attechment = null; int isAttechment = BinaryEncoder.ReadInt(stream); if (isAttechment == 1) { attechment = BinaryEncoder.ReceiveBytes(stream); } IJType jmessage; switch (type) { case JsonTypes.ALARM: jmessage = JsonConvert.DeserializeObject <JAlarm>(jsonText); break; case JsonTypes.CONTACT: jmessage = JsonConvert.DeserializeObject <JContact>(jsonText); break; case JsonTypes.MESSAGES: jmessage = JsonConvert.DeserializeObject <JMessage>(jsonText); break; case JsonTypes.MESSAGES_THREAD: jmessage = JsonConvert.DeserializeObject <JMessageThread>(jsonText); break; default: throw new Exception("Unknown JsonType."); } return(new JsonCapsula() { Attechment = attechment, Message = jmessage }); }
static void AesTrial() { using (Context context = new Context(config)) { byte[] aesBinKey = context.Contacts .Where(u => u.PublicId == connection.UserId) .Select(u => u.ReceiveAesKey) .SingleOrDefault(); AESPassword key = new AESPassword(aesBinKey); String testStr = "Testy tisty teristy\n"; for (int i = 0; i != 3; i++) { testStr += testStr; } WriteLine($"Encrypting string: {testStr}"); byte[] data = Encoding.UTF8.GetBytes(testStr); byte[] encrypted = key.Encrypt(data); WriteLine(Encoding.UTF8.GetString(key.Decrypt(encrypted))); } }
public static byte[] GetJsonEncoded(Context context, IJType message, long receiverId) { byte[] aesBinKey = context.Contacts .Where(u => u.PublicId == receiverId) .Select(u => u.SendAesKey) .SingleOrDefault(); AESPassword key = new AESPassword(aesBinKey); MemoryStream stream = new MemoryStream(); stream.WriteByte((byte)message.GetJsonType()); string json = JsonConvert.SerializeObject(message); StreamWriter writer = new StreamWriter(stream, Encoding.UTF8); writer.Write(json); writer.Close(); byte[] notEncrypted = stream.ToArray(); return(key.Encrypt(notEncrypted)); }
/// <summary> /// 这是一次彻底的重连,重新获取服务器地址的重连,以下情况下才会调用该方法: /// 1,进程启动后第一次连接时; /// 2,连不上服务器时; /// 3,收到服务器的WsMessage.ReGetServerAddress类型的消息时; /// </summary> /// <returns></returns> private void NewWebSocket(Action <WebSocket> callback) { RpcRoot.OfficialServer.WsServerNodeService.GetNodeAddressAsync(NTMinerRegistry.GetClientId(_appType), _outerUserId, (response, ex) => { LastTryOn = DateTime.Now; if (!response.IsSuccess()) { IncreaseFailCount(); UpdateNextTrySecondsDelay(); string description; if (response == null || response.ReasonPhrase == null) { description = "网络错误"; } else { description = response.ReadMessage(ex); } UpdateWsStateAsync(description, toOut: false); callback?.Invoke(null); // 退出 return; } string server = response.Data; if (string.IsNullOrEmpty(server)) { IncreaseFailCount(); UpdateNextTrySecondsDelay(); UpdateWsStateAsync("服务器不在线", toOut: false); callback?.Invoke(null); // 退出 return; } var ws = new WebSocket($"ws://{server}/{_appType.GetName()}"); ws.OnOpen += (sender, e) => { ResetFailCount(); UpdateWsStateAsync("连接服务器成功", toOut: false); }; ws.OnMessage += (sender, e) => { if (_ws != ws) { return; } #region if (e.IsPing) { return; } WsMessage message = null; if (e.IsBinary) { message = VirtualRoot.BinarySerializer.Deserialize <WsMessage>(e.RawData); } else // 此时一定IsText,因为取值只有IsBinary、IsPing、IsText这三种 { if (string.IsNullOrEmpty(e.Data) || e.Data[0] != '{' || e.Data[e.Data.Length - 1] != '}') { return; } message = VirtualRoot.JsonSerializer.Deserialize <WsMessage>(e.Data); } if (message == null) { return; } switch (_appType) { case NTMinerAppType.MinerClient: if (message.Type == WsMessage.UpdateAESPassword) { if (message.TryGetData(out AESPassword aesPassword)) { aesPassword.Password = Cryptography.RSAUtil.DecryptString(aesPassword.Password, aesPassword.PublicKey); _aesPassword = aesPassword; } return; } if (_aesPassword == null) { return; } if (message.Sign != message.CalcSign(_aesPassword.Password)) { UpdateWsStateAsync(description: "来自群控的消息签名错误", toOut: true); return; } break;
public void TrustContact(int contactId) { ThrowExceptionIfNotConnected(); Pull(); lock (mutex) { Log("Sending TRUST_CONTACT command."); BinaryEncoder.SendCommand(stream, ConnectionCommand.TRUST_CONTACT); BinaryEncoder.SendInt(stream, contactId); using (Context context = new Context(config)) { var contact = new UContact(context.Contacts .Where(u => u.PublicId == contactId) .SingleOrDefault()) { Trusted = true }; if (contact.SendAesKey == null) { Log("Sending new key."); BinaryEncoder.SendInt(stream, 1); AESPassword password = AESPassword.GenerateAESPassword(); contact.SendAesKey = password.Password; X509Certificate2 recepientCert = X509Certificate2Utils.ImportFromPem( context.Contacts .Where(u => u.PublicId == contactId) .Select(u => u.PublicCertificate) .SingleOrDefault()); byte[] toSend = RSAEncoder.EncryptAndSign(password.Password, recepientCert, MyCertificate); BinaryEncoder.SendBytes(stream, toSend); } else { Log("No new key will be sended."); BinaryEncoder.SendInt(stream, 0); } if (contactId != this.UserId) { PushOperations.SendJsonCapsula(context, contact.GetSelfUpdate(), UserId, UserId); } else { var me = context.Contacts .Where(u => u.PublicId == UserId) .Single(); me.SendAesKey = contact.SendAesKey; me.ReceiveAesKey = contact.ReceiveAesKey; } context.SaveChanges(); } Log("Trustification has been done."); } Push(); }
private void Ws_OnMessage(object sender, MessageEventArgs e) { WebSocket ws = (WebSocket)sender; if (_ws != ws) { return; } #region if (e.IsPing) { return; } WsMessage message = null; if (e.IsBinary) { message = VirtualRoot.BinarySerializer.Deserialize <WsMessage>(e.RawData); } else // 此时一定IsText,因为取值只有IsBinary、IsPing、IsText这三种 { if (string.IsNullOrEmpty(e.Data) || e.Data[0] != '{' || e.Data[e.Data.Length - 1] != '}') { return; } message = VirtualRoot.JsonSerializer.Deserialize <WsMessage>(e.Data); } if (message == null) { return; } switch (_appType) { case NTMinerAppType.MinerClient: if (message.Type == WsMessage.UpdateAESPassword) { if (message.TryGetData(out AESPassword aesPassword)) { aesPassword.Password = Cryptography.RSAUtil.DecryptString(aesPassword.Password, aesPassword.PublicKey); _aesPassword = aesPassword; } return; } if (_aesPassword == null) { return; } if (message.Sign != message.CalcSign(_aesPassword.Password)) { UpdateWsStateAsync(description: "来自群控的消息签名错误", toOut: true); return; } break; case NTMinerAppType.MinerStudio: if (message.Type == WsMessage.ReLogin) { UpdateWsStateAsync(description: "用户密码已变更,请重新登录", toOut: true); return; } if (message.Sign != message.CalcSign(RpcRoot.RpcUser.Password)) { UpdateWsStateAsync(description: "来自群控的消息签名错误", toOut: true); return; } break; default: break; } if (message.Type == WsMessage.ReGetServerAddress) { ws.CloseAsync(CloseStatusCode.Normal, WsMessage.ReGetServerAddress); return; } if (TryGetHandler(message.Type, out Action <Action <WsMessage>, WsMessage> handler)) { handler.Invoke(SendAsync, message); } else { NTMinerConsole.DevWarn(() => $"OnMessage Received InvalidType {e.Data}"); } #endregion }
public JAESKey(long UserId, AESPassword password) { this.UserId = UserId; this.AESKey = password.Password; }