bytewalker 0 Posted ... (edited) Hi guys I'm a new user I just joined not too long ago. I tried making a comment yesterday for some reason it disappeared? There were some speed issues with the servers but they subsided. Anyways I was taking a look at the code (hope that's okay) and saw the following: /src/Lib.Core/Providers/Service.cs First you say when you're bootstrapping directly via IP you can't use TLS but surely there must be some other way to encrypt the tunnel itself instead of manually fiddling with the data? Then you use base64 to encode the modulus and exponent and go on as to manually build up the key instead of using a PEM file or the like, then you manually encrypt the data and fiddle around with the string? I don't really get the thought process behind this. Why not just register a domain then or simply use some other means of transferring the data? Why not just take the data (username / password for example) and manually encrypt it with a public key (imported via a PEM file) and transfer it like that if your not using TLS? Why make this so complicated? Could you please also lift the posting restrictions for paid users? Apparently you can only post once a day and your comments need to be manually approved. I get that you need to take measures to prevent spam but for paid users surely there can be some more restrictions? I saw a few interesting posts yesterday but couldn't comment on them because of this. // Intentional: AirVPN bootstrap uses HTTP without TLS; payload is AES-256 with RSA-wrapped session key (see below). // Direct IP bootstrap URLs cannot rely on TLS common-name validation. // 'S' is the AES 256 bit one-time session key, crypted with a RSA 4096 public-key. // 'D' is the data from the client to our server, crypted with the AES. // The server answer is XML decrypted with the same AES session. public static byte[] AssocToUtf8Bytes(Dictionary<string, string> assoc) { string output = ""; foreach (KeyValuePair<string, string> kp in assoc) { output += ExtensionsString.Base64Encode(kp.Key.GetUtf8Bytes()) + ":" + ExtensionsString.Base64Encode(kp.Value.GetUtf8Bytes()) + "\n"; } return System.Text.Encoding.UTF8.GetBytes(output); } public static byte[] AssocToUtf8Bytes(Dictionary<string, byte[]> assoc) { string output = ""; foreach (KeyValuePair<string, byte[]> kp in assoc) { output += ExtensionsString.Base64Encode(kp.Key.GetUtf8Bytes()) + ":" + ExtensionsString.Base64Encode(kp.Value) + "\n"; } return System.Text.Encoding.UTF8.GetBytes(output); } public XmlDocument FetchUrl(string url, Dictionary<string, string> parameters) { using (Aes aes = Aes.Create()) { aes.KeySize = 256; aes.GenerateKey(); aes.GenerateIV(); // Generate S string rsaModulus = ""; string rsaExponent = ""; if (Manifest.GetAttributeString("auth_rsa_modulus", "") != "") { rsaModulus = Manifest.GetAttributeString("auth_rsa_modulus", ""); rsaExponent = Manifest.GetAttributeString("auth_rsa_exponent", ""); } else // Compatibility <2.21.0 { rsaModulus = Manifest.SelectSingleNode("rsa/RSAParameters/Modulus").InnerText; rsaExponent = Manifest.SelectSingleNode("rsa/RSAParameters/Exponent").InnerText; } RSAParameters publicKey = new RSAParameters(); publicKey.Modulus = Convert.FromBase64String(rsaModulus); publicKey.Exponent = Convert.FromBase64String(rsaExponent); Dictionary<string, byte[]> assocParamS = new Dictionary<string, byte[]>(); assocParamS["key"] = aes.Key; assocParamS["iv"] = aes.IV; byte[] bytesParamS = null; using (RSACryptoServiceProvider csp = new RSACryptoServiceProvider()) { csp.ImportParameters(publicKey); bytesParamS = csp.Encrypt(AssocToUtf8Bytes(assocParamS), false); } // Generate D byte[] aesDataIn = AssocToUtf8Bytes(parameters); byte[] bytesParamD = null; { MemoryStream aesCryptStream = null; CryptoStream aesCryptStream2 = null; try { aesCryptStream = new MemoryStream(); using (ICryptoTransform aesEncryptor = aes.CreateEncryptor()) { aesCryptStream2 = new CryptoStream(aesCryptStream, aesEncryptor, CryptoStreamMode.Write); aesCryptStream2.Write(aesDataIn, 0, aesDataIn.Length); aesCryptStream2.FlushFinalBlock(); bytesParamD = aesCryptStream.ToArray(); } } finally { if (aesCryptStream2 != null) aesCryptStream2.Dispose(); else if (aesCryptStream != null) aesCryptStream.Dispose(); } } Edited ... by darkocean69 Quote Share this post Link to post
Staff 10581 Posted ... @darkocean69 Hello! Good question. In 2010 we wanted an encrypted stream without HTTPS and/or certificates that looked as much as possible as plain HTTP for good reasons. We also wanted to avoid importing public keys and make the procedure immediately usable on the software. The method was good enough to survive for 16 years. Now we can also implement potentially bootstrap server access via HTTPS or more esotic ways but there's really no need at the moment, we'll see. Kind regards Quote Share this post Link to post