Jump to content
Not connected, Your IP: 216.73.216.185
Sign in to follow this  

Recommended Posts

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

Share this post


Link to post
@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
 

Share this post


Link to post

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...
  • Security Check
    Play CAPTCHA Audio
    Refresh Image
Sign in to follow this  

×
×
  • Create New...