");
105 | sb.Append("" + Convert.ToBase64String(rsaParams.Modulus) + "");
106 | sb.Append("" + Convert.ToBase64String(rsaParams.Exponent) + "");
107 |
108 | if (includePrivateParameters)
109 | {
110 | sb.Append("" + Convert.ToBase64String(rsaParams.P) + "
");
111 | sb.Append("" + Convert.ToBase64String(rsaParams.Q) + "
");
112 | sb.Append("" + Convert.ToBase64String(rsaParams.DP) + "");
113 | sb.Append("" + Convert.ToBase64String(rsaParams.DQ) + "");
114 | sb.Append("" + Convert.ToBase64String(rsaParams.InverseQ) + "");
115 | sb.Append("" + Convert.ToBase64String(rsaParams.D) + "");
116 | }
117 |
118 | sb.Append("");
119 |
120 | return sb.ToString();
121 | }
122 |
123 | private static RSAParameters CreateRsaParamsFromXmlString(string xmlString)
124 | {
125 | var parameters = new RSAParameters();
126 |
127 | var xmlDoc = new XmlDocument();
128 | xmlDoc.LoadXml(xmlString);
129 |
130 | if (xmlDoc.DocumentElement.Name.Equals("RSAKeyValue"))
131 | {
132 | foreach (XmlNode node in xmlDoc.DocumentElement.ChildNodes)
133 | {
134 | switch (node.Name)
135 | {
136 | case "Modulus":
137 | parameters.Modulus = Convert.FromBase64String(node.InnerText);
138 |
139 | break;
140 | case "Exponent":
141 | parameters.Exponent = Convert.FromBase64String(node.InnerText);
142 |
143 | break;
144 | case "P":
145 | parameters.P = Convert.FromBase64String(node.InnerText);
146 |
147 | break;
148 | case "Q":
149 | parameters.Q = Convert.FromBase64String(node.InnerText);
150 |
151 | break;
152 | case "DP":
153 | parameters.DP = Convert.FromBase64String(node.InnerText);
154 |
155 | break;
156 | case "DQ":
157 | parameters.DQ = Convert.FromBase64String(node.InnerText);
158 |
159 | break;
160 | case "InverseQ":
161 | parameters.InverseQ = Convert.FromBase64String(node.InnerText);
162 |
163 | break;
164 | case "D":
165 | parameters.D = Convert.FromBase64String(node.InnerText);
166 |
167 | break;
168 | }
169 | }
170 | }
171 | else
172 | {
173 | throw new ArgumentException("Invalid XML RSA key.");
174 | }
175 |
176 | return parameters;
177 | }
178 |
179 | public string GetSha256Fingerprint()
180 | {
181 | if (this.rsa == null)
182 | {
183 | throw new InvalidOperationException();
184 | }
185 |
186 | var rsaParams = this.rsa.ExportParameters(false);
187 |
188 | byte[] hashBytes;
189 | using (SHA256 sha256 = new SHA256Managed())
190 | {
191 | hashBytes = sha256.ComputeHash(rsaParams.Modulus);
192 | }
193 |
194 | var sb = new StringBuilder(95);
195 | for (var i = 0; i < hashBytes.Length; i++)
196 | {
197 | byte b = hashBytes[i];
198 | sb.Append(b.ToString("X2"));
199 |
200 | if (i < hashBytes.Length - 1)
201 | {
202 | sb.Append(':');
203 | }
204 | }
205 |
206 | return sb.ToString();
207 | }
208 | }
209 | }
--------------------------------------------------------------------------------
/EncryptedChat/EncryptedChat.Client.App/Engine.cs:
--------------------------------------------------------------------------------
1 | namespace EncryptedChat.Client.App
2 | {
3 | using System;
4 | using System.Linq;
5 | using System.Text.RegularExpressions;
6 | using System.Threading.Tasks;
7 | using Common;
8 | using Common.Configuration;
9 | using Common.Crypto;
10 | using Microsoft.AspNetCore.SignalR.Client;
11 | using Common.Models;
12 |
13 | public class Engine
14 | {
15 | private HubConnection connection;
16 | private EncryptedCommunicationsManager communicationsManager;
17 | private ConfigurationManager