如何加密发送至Azure SignalR Service支持的SignalR群组的消息
实现方案
核心思路:端到端加密,Azure Function仅做转发
不让Azure Function接触明文消息和密钥,所有加密、解密操作都在客户端完成,密钥仅在群组合法成员之间共享。
1. 群组共享密钥协商
- 每个客户端生成自己的RSA密钥对,加入群组时将公钥发送给群组内其他成员(可通过SignalR的用户点对点消息传递,或经过Azure Function转发但Function不解析内容)。
- 由群组内指定成员(比如第一个加入的用户)生成AES对称密钥,用每个群组成员的公钥分别加密该密钥,发送给对应成员;成员用自身私钥解密得到AES密钥。
- 若有成员离开群组,剩余成员需重新协商新的AES密钥,防止已离开成员继续解密后续消息。
2. 客户端侧消息加密/解密
发送消息时加密
// 假设已通过协商获取到群组共享AES密钥aesKey byte[] plainTextBytes = Encoding.UTF8.GetBytes(message); byte[] encryptedBytes = AesEncrypt(plainTextBytes, aesKey); string encryptedMessage = Convert.ToBase64String(encryptedBytes); // 发送加密后的密文到SignalR Hub await hubConnection.SendAsync("msgSent", username, encryptedMessage);
接收消息时解密
hubConnection.On<string>("msgReceived", (encryptedMessage) => { byte[] encryptedBytes = Convert.FromBase64String(encryptedMessage); byte[] plainTextBytes = AesDecrypt(encryptedBytes, aesKey); string message = Encoding.UTF8.GetString(plainTextBytes); // 处理明文消息逻辑 });
3. 调整Azure Function代码
Function无需任何加密/解密逻辑,仅负责转发密文:
[Function("SendMessageToGroup")] [SignalROutput(HubName = "MyHub")] public SignalRMessageAction SendMessageToGroup( [SignalRTrigger("MyHub", "Category", "msgSent", "username", "encryptedMessage")] SignalRInvocationContext invocationContext, string username, string encryptedMessage) { // 直接转发密文,不接触明文内容 return new SignalRMessageAction() { Arguments = [encryptedMessage], GroupName = "MyGroup" }; }
4. 辅助加密工具示例(AES实现)
private static byte[] AesEncrypt(byte[] plainText, byte[] key) { using (Aes aesAlg = Aes.Create()) { aesAlg.Key = key; aesAlg.GenerateIV(); ICryptoTransform encryptor = aesAlg.CreateEncryptor(aesAlg.Key, aesAlg.IV); using (MemoryStream msEncrypt = new MemoryStream()) { msEncrypt.Write(aesAlg.IV, 0, aesAlg.IV.Length); using (CryptoStream csEncrypt = new CryptoStream(msEncrypt, encryptor, CryptoStreamMode.Write)) { csEncrypt.Write(plainText, 0, plainText.Length); csEncrypt.FlushFinalBlock(); } return msEncrypt.ToArray(); } } } private static byte[] AesDecrypt(byte[] cipherText, byte[] key) { using (Aes aesAlg = Aes.Create()) { aesAlg.Key = key; byte[] iv = new byte[aesAlg.BlockSize / 8]; Array.Copy(cipherText, 0, iv, 0, iv.Length); aesAlg.IV = iv; ICryptoTransform decryptor = aesAlg.CreateDecryptor(aesAlg.Key, aesAlg.IV); using (MemoryStream msDecrypt = new MemoryStream(cipherText, iv.Length, cipherText.Length - iv.Length)) { using (CryptoStream csDecrypt = new CryptoStream(msDecrypt, decryptor, CryptoStreamMode.Read)) { using (MemoryStream resultStream = new MemoryStream()) { csDecrypt.CopyTo(resultStream); return resultStream.ToArray(); } } } } }
内容的提问来源于stack exchange,提问作者Arash
相关产品推荐
相关产品推荐

