public void TestMd5() { var buff = Encoding.UTF8.GetBytes(@"密码"); var md5Sum = MbedTLS.MD5(buff); var md5Hash = MD5.Create().ComputeHash(buff); Assert.IsTrue(md5Hash.SequenceEqual(md5Sum)); }
protected override void initCipher(byte[] iv, bool isCipher) { base.initCipher(iv, isCipher); var cipherInfo = OpenSSL.GetCipherInfo(_innerLibName); if (cipherInfo == IntPtr.Zero) { throw new Exception("openssl: cipher not found"); } var ctx = OpenSSL.EVP_CIPHER_CTX_new(); if (ctx == IntPtr.Zero) { throw new Exception("fail to create ctx"); } if (isCipher) { _encryptCtx = ctx; } else { _decryptCtx = ctx; } byte[] realKey; if (_method.StartsWith(@"rc4-md5")) { var temp = new byte[keyLen + ivLen]; Array.Copy(_key, 0, temp, 0, keyLen); Array.Copy(iv, 0, temp, keyLen, ivLen); realKey = MbedTLS.MD5(temp); } else { realKey = _key; } var ret = OpenSSL.EVP_CipherInit_ex(ctx, cipherInfo, IntPtr.Zero, null, null, isCipher ? OpenSSL.OPENSSL_ENCRYPT : OpenSSL.OPENSSL_DECRYPT); if (ret != 1) { throw new Exception("openssl: fail to set key length"); } ret = OpenSSL.EVP_CIPHER_CTX_set_key_length(ctx, keyLen); if (ret != 1) { throw new Exception("openssl: fail to set key length"); } ret = OpenSSL.EVP_CipherInit_ex(ctx, IntPtr.Zero, IntPtr.Zero, realKey, _method == "rc4-md5" ? null : iv, isCipher ? OpenSSL.OPENSSL_ENCRYPT : OpenSSL.OPENSSL_DECRYPT); if (ret != 1) { throw new Exception("openssl: cannot set key and iv"); } OpenSSL.EVP_CIPHER_CTX_set_padding(ctx, 0); }
protected override void initCipher(byte[] iv, bool isCipher) { base.initCipher(iv, isCipher); IntPtr ctx = Marshal.AllocHGlobal(MbedTLS.cipher_get_size_ex()); if (isCipher) { _encryptCtx = ctx; } else { _decryptCtx = ctx; } byte[] realkey; if (_method.StartsWith("rc4-")) { byte[] temp = new byte[keyLen + ivLen]; realkey = new byte[keyLen]; Array.Copy(_key, 0, temp, 0, keyLen); Array.Copy(iv, 0, temp, keyLen, ivLen); realkey = MbedTLS.MD5(temp); } else { realkey = _key; } MbedTLS.cipher_init(ctx); if (MbedTLS.cipher_setup(ctx, MbedTLS.cipher_info_from_string(getInfo().name)) != 0) { throw new Exception("Cannot initialize mbed TLS cipher context"); } /* * MbedTLS takes key length by bit * cipher_setkey() will set the correct key schedule * and operation * * MBEDTLS_AES_{EN,DE}CRYPT * == MBEDTLS_BLOWFISH_{EN,DE}CRYPT * == MBEDTLS_CAMELLIA_{EN,DE}CRYPT * == MBEDTLS_{EN,DE}CRYPT * */ if (MbedTLS.cipher_setkey(ctx, realkey, keyLen * 8, isCipher ? MbedTLS.MBEDTLS_ENCRYPT : MbedTLS.MBEDTLS_DECRYPT) != 0) { throw new Exception("Cannot set mbed TLS cipher key"); } if (MbedTLS.cipher_set_iv(ctx, iv, ivLen) != 0) { throw new Exception("Cannot set mbed TLS cipher IV"); } if (MbedTLS.cipher_reset(ctx) != 0) { throw new Exception("Cannot finalize mbed TLS cipher context"); } }
public void DeriveSessionKey(byte[] salt, byte[] masterKey, byte[] sessionKey) { int ret = MbedTLS.hkdf(salt, saltLen, masterKey, keyLen, InfoBytes, InfoBytes.Length, sessionKey, keyLen); if (ret != 0) { throw new System.Exception("failed to generate session key"); } }
public void TestMD5() { for (int len = 1; len < 64; len++) { System.Security.Cryptography.MD5 md5 = System.Security.Cryptography.MD5.Create(); byte[] bytes = new byte[len]; _random.NextBytes(bytes); string md5str = Convert.ToBase64String(md5.ComputeHash(bytes)); string md5str2 = Convert.ToBase64String(MbedTLS.MD5(bytes)); Assert.IsTrue(md5str == md5str2); } }
protected override void cipherUpdate(bool isCipher, int length, byte[] buf, byte[] outbuf) { // C# could be multi-threaded if (_disposed) { throw new ObjectDisposedException(ToString()); } if (MbedTLS.cipher_update(isCipher ? _encryptCtx : _decryptCtx, buf, length, outbuf, ref length) != 0) { throw new Exception("Cannot update mbed TLS cipher context"); } }
protected override void cipherUpdate(bool isEncrypt, int length, byte[] buf, byte[] outbuf) { // C# could be multi-threaded if (_disposed) { throw new ObjectDisposedException(this.ToString()); } if (MbedTLS.cipher_update(isEncrypt ? _encryptCtx : _decryptCtx, buf, length, outbuf, ref length) != 0) { throw new CryptoErrorException(); } }
// UDP: master key // TCP: session key private void CipherSetKey(bool isEncrypt, byte[] key) { IntPtr ctx = isEncrypt ? _encryptCtx : _decryptCtx; int ret = MbedTLS.cipher_setkey(ctx, key, keyLen * 8, isEncrypt ? MbedTLS.MBEDTLS_ENCRYPT : MbedTLS.MBEDTLS_DECRYPT); if (ret != 0) { throw new System.Exception("failed to set key"); } ret = MbedTLS.cipher_reset(ctx); if (ret != 0) { throw new System.Exception("failed to finish preparation"); } }
public override byte[] ClientUdpPreEncrypt(byte[] plaindata, int datalength, out int outlength) { byte[] outdata = new byte[datalength + 1024]; if (user_key == null) { user_id = new byte[4]; int index_of_split = Server.param.IndexOf(':'); if (index_of_split > 0) { try { uint user = uint.Parse(Server.param.Substring(0, index_of_split)); user_key = System.Text.Encoding.UTF8.GetBytes(Server.param.Substring(index_of_split + 1)); BitConverter.GetBytes(user).CopyTo(user_id, 0); } catch (Exception ex) { Logging.Log(LogLevel.Warn, $"Faild to parse auth param, fallback to basic mode. {ex}"); } } if (user_key == null) { random.NextBytes(user_id); user_key = Server.key; } } byte[] auth_data = new byte[3]; random.NextBytes(auth_data); byte[] md5data = MbedTLS.ComputeHash(Server.key, auth_data, 0, auth_data.Length); int rand_len = UdpGetRandLen(random_client, md5data); byte[] rand_data = new byte[rand_len]; random.NextBytes(rand_data); outlength = datalength + rand_len + 8; encryptor = EncryptorFactory.GetEncryptor("rc4", Convert.ToBase64String(user_key) + Convert.ToBase64String(md5data, 0, 16)); encryptor.Encrypt(plaindata, datalength, outdata, out datalength); rand_data.CopyTo(outdata, datalength); auth_data.CopyTo(outdata, outlength - 8); byte[] uid = new byte[4]; for (int i = 0; i < 4; ++i) { uid[i] = (byte)(user_id[i] ^ md5data[i]); } uid.CopyTo(outdata, outlength - 5); md5data = MbedTLS.ComputeHash(user_key, outdata, 0, outlength - 1); return(outdata); }
public void PackData(byte[] data, int datalength, byte[] outdata, out int outlength) { int rand_len = GetRandLen(datalength); outlength = rand_len + datalength + 2; outdata[0] = (byte)(datalength ^ last_client_hash[14]); outdata[1] = (byte)((datalength >> 8) ^ last_client_hash[15]); { byte[] rnd_data = new byte[rand_len]; random.NextBytes(rnd_data); encryptor.Encrypt(data, datalength, data, out datalength); if (datalength > 0) { if (rand_len > 0) { int start_pos = GetRandStartPos(rand_len, random_client); Array.Copy(data, 0, outdata, 2 + start_pos, datalength); Array.Copy(rnd_data, 0, outdata, 2, start_pos); Array.Copy(rnd_data, start_pos, outdata, 2 + start_pos + datalength, rand_len - start_pos); } else { Array.Copy(data, 0, outdata, 2, datalength); } } else { rnd_data.CopyTo(outdata, 2); } } byte[] key = new byte[user_key.Length + 4]; user_key.CopyTo(key, 0); BitConverter.GetBytes(pack_id).CopyTo(key, key.Length - 4); ++pack_id; byte[] md5data = MbedTLS.ComputeHash(key, outdata, 0, outlength); last_client_hash = md5data; Array.Copy(md5data, 0, outdata, outlength, 2); outlength += 2; }
public override byte[] ClientUdpPostDecrypt(byte[] plaindata, int datalength, out int outlength) { if (datalength <= 8) { outlength = 0; return(plaindata); } byte[] md5data = MbedTLS.ComputeHash(user_key, plaindata, 0, datalength - 1); if (md5data[0] != plaindata[datalength - 1]) { outlength = 0; return(plaindata); } md5data = MbedTLS.ComputeHash(Server.key, plaindata, datalength - 8, 7); int rand_len = UdpGetRandLen(random_server, md5data); outlength = datalength - rand_len - 8; encryptor = EncryptorFactory.GetEncryptor("rc4", Convert.ToBase64String(user_key) + Convert.ToBase64String(md5data, 0, 16)); encryptor.Decrypt(plaindata, outlength, plaindata, out outlength); return(plaindata); }
public static void LegacyDeriveKey(byte[] password, byte[] key, int keylen) { byte[] result = new byte[password.Length + MD5_LEN]; int i = 0; byte[] md5sum = null; while (i < keylen) { if (i == 0) { md5sum = MbedTLS.MD5(password); } else { Array.Copy(md5sum, 0, result, 0, MD5_LEN); Array.Copy(password, 0, result, MD5_LEN, password.Length); md5sum = MbedTLS.MD5(result); } Array.Copy(md5sum, 0, key, i, Math.Min(MD5_LEN, keylen - i)); i += MD5_LEN; } }
public static void LegacyDeriveKey(byte[] password, byte[] key) { byte[] result = new byte[password.Length + 16]; int i = 0; byte[] md5sum = null; while (i < key.Length) { if (i == 0) { md5sum = MbedTLS.MD5(password); } else { md5sum.CopyTo(result, 0); password.CopyTo(result, md5sum.Length); md5sum = MbedTLS.MD5(result); } md5sum.CopyTo(key, i); i += md5sum.Length; } }
public static void bytesToKey(byte[] password, byte[] key) { var result = new byte[password.Length + 16]; var i = 0; byte[] md5Sum = null; while (i < key.Length) { if (i == 0) { md5Sum = MbedTLS.MD5(password); } else { Debug.Assert(md5Sum != null, $@"{nameof(md5Sum)} != null"); md5Sum.CopyTo(result, 0); password.CopyTo(result, md5Sum.Length); md5Sum = MbedTLS.MD5(result); } md5Sum.CopyTo(key, i); i += md5Sum.Length; } }
public override void InitCipher(byte[] salt, bool isEncrypt, bool isUdp) { base.InitCipher(salt, isEncrypt, isUdp); IntPtr ctx = Marshal.AllocHGlobal(MbedTLS.cipher_get_size_ex()); if (isEncrypt) { _encryptCtx = ctx; } else { _decryptCtx = ctx; } MbedTLS.cipher_init(ctx); if (MbedTLS.cipher_setup(ctx, MbedTLS.cipher_info_from_string(_innerLibName)) != 0) { throw new System.Exception("Cannot initialize mbed TLS cipher context"); } DeriveSessionKey(isEncrypt ? _encryptSalt : _decryptSalt, _Masterkey, _sessionKey); CipherSetKey(isEncrypt, _sessionKey); }
public override void cipherEncrypt(byte[] plaintext, uint plen, byte[] ciphertext, ref uint clen) { // buf: all plaintext // outbuf: ciphertext + tag int ret; byte[] tagbuf = new byte[tagLen]; uint olen = 0; switch (_cipher) { case CIPHER_AES: ret = MbedTLS.cipher_auth_encrypt(_encryptCtx, /* nonce */ _encNonce, (uint)nonceLen, /* AD */ IntPtr.Zero, 0, /* plain */ plaintext, plen, /* cipher */ ciphertext, ref olen, tagbuf, (uint)tagLen); if (ret != 0) { throw new CryptoErrorException(String.Format("ret is {0}", ret)); } Debug.Assert(olen == plen); // attach tag to ciphertext Array.Copy(tagbuf, 0, ciphertext, (int)plen, tagLen); clen = olen + (uint)tagLen; break; default: throw new System.Exception("not implemented"); } }
private static string GetHash(string content) { return(Uri.EscapeUriString(BitConverter.ToString(MbedTLS.MD5(Encoding.ASCII.GetBytes(content))).Replace("-", ""))); }
public void PackAuthData(byte[] data, int datalength, byte[] outdata, out int outlength) { const int authhead_len = 4 + 8 + 4 + 16 + 4; byte[] encrypt = new byte[24]; AuthDataAesChain authData = Server.data as AuthDataAesChain; lock (authData) { if (authData.connectionID > 0xFF000000) { authData.clientID = null; } if (authData.clientID == null) { authData.clientID = new byte[4]; g_random.GetBytes(authData.clientID); authData.connectionID = (UInt32)BitConverter.ToInt32(authData.clientID, 0) % 0xFFFFFD; } authData.connectionID += 1; Array.Copy(authData.clientID, 0, encrypt, 4, 4); Array.Copy(BitConverter.GetBytes(authData.connectionID), 0, encrypt, 8, 4); } outlength = authhead_len; byte[] encrypt_data = new byte[32]; byte[] key = new byte[Server.iv.Length + Server.key.Length]; Server.iv.CopyTo(key, 0); Server.key.CopyTo(key, Server.iv.Length); UInt64 utc_time_second = (UInt64)Math.Floor(DateTime.UtcNow.Subtract(new DateTime(1970, 1, 1, 0, 0, 0)).TotalSeconds); UInt32 utc_time = (UInt32)(utc_time_second); Array.Copy(BitConverter.GetBytes(utc_time), 0, encrypt, 0, 4); encrypt[12] = (byte)(Server.overhead); encrypt[13] = (byte)(Server.overhead >> 8); // first 12 bytes { byte[] rnd = new byte[4]; random.NextBytes(rnd); rnd.CopyTo(outdata, 0); byte[] md5data = MbedTLS.ComputeHash(key, rnd, 0, rnd.Length); last_client_hash = md5data; Array.Copy(md5data, 0, outdata, rnd.Length, 8); } // uid & 16 bytes auth data { byte[] uid = new byte[4]; int index_of_split = Server.param.IndexOf(':'); if (index_of_split > 0) { try { uint user = uint.Parse(Server.param.Substring(0, index_of_split)); user_key = System.Text.Encoding.UTF8.GetBytes(Server.param.Substring(index_of_split + 1)); BitConverter.GetBytes(user).CopyTo(uid, 0); } catch (Exception ex) { Logging.Log(LogLevel.Warn, $"Faild to parse auth param, fallback to basic mode. {ex}"); } } if (user_key == null) { random.NextBytes(uid); user_key = Server.key; } for (int i = 0; i < 4; ++i) { uid[i] ^= last_client_hash[8 + i]; } byte[] encrypt_key = user_key; IEncryptor encryptor = EncryptorFactory.GetEncryptor("aes-128-cbc", Convert.ToBase64String(encrypt_key) + SALT); encryptor.SetIV(new byte[] { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }); encryptor.Encrypt(encrypt, 16, encrypt_data, out int enc_outlen); encryptor.Dispose(); Array.Copy(encrypt_data, 16, encrypt, 4, 16); uid.CopyTo(encrypt, 0); } // final HMAC { byte[] md5data = MbedTLS.ComputeHash(user_key, encrypt, 0, 20); last_server_hash = md5data; Array.Copy(md5data, 0, encrypt, 20, 4); } encrypt.CopyTo(outdata, 12); encryptor = EncryptorFactory.GetEncryptor("rc4", Convert.ToBase64String(user_key) + Convert.ToBase64String(last_client_hash, 0, 16)); // combine first chunk { byte[] pack_outdata = new byte[outdata.Length]; PackData(data, datalength, pack_outdata, out int pack_outlength); Array.Copy(pack_outdata, 0, outdata, outlength, pack_outlength); outlength += pack_outlength; } }
public override byte[] ClientPostDecrypt(byte[] plaindata, int datalength, out int outlength) { byte[] outdata = new byte[recv_buf_len + datalength]; Array.Copy(plaindata, 0, recv_buf, recv_buf_len, datalength); recv_buf_len += datalength; outlength = 0; byte[] key = new byte[user_key.Length + 4]; user_key.CopyTo(key, 0); while (recv_buf_len > 4) { BitConverter.GetBytes(recv_id).CopyTo(key, key.Length - 4); int data_len = ((recv_buf[1] ^ last_server_hash[15]) << 8) + (recv_buf[0] ^ last_server_hash[14]); int rand_len = GetRandLen(data_len, random_server, last_server_hash); int len = rand_len + data_len; if (len >= 4096) { throw new ObfsException("ClientPostDecrypt data error"); } if (len + 4 > recv_buf_len) { break; } byte[] md5data = MbedTLS.ComputeHash(key, recv_buf, 0, len + 2); if (md5data[0] != recv_buf[len + 2] || md5data[1] != recv_buf[len + 3]) { throw new ObfsException("ClientPostDecrypt data uncorrect checksum"); } int pos; if (data_len > 0 && rand_len > 0) { pos = 2 + GetRandStartPos(rand_len, random_server); } else { pos = 2; } int outlen = data_len; Util.Utils.SetArrayMinSize2(ref outdata, outlength + outlen); byte[] data = new byte[outlen]; Array.Copy(recv_buf, pos, data, 0, outlen); encryptor.Decrypt(data, outlen, data, out outlen); last_server_hash = md5data; if (recv_id == 1) { Server.tcp_mss = data[0] | (data[1] << 8); pos = 2; outlen -= 2; } else { pos = 0; } Array.Copy(data, pos, outdata, outlength, outlen); outlength += outlen; recv_buf_len -= len + 4; Array.Copy(recv_buf, len + 4, recv_buf, 0, recv_buf_len); ++recv_id; } return(outdata); }
private static string GetHash(string content) { return(HttpServerUtility.UrlTokenEncode(MbedTLS.MD5(Encoding.ASCII.GetBytes(content)))); }