From f50aca6691fd6fc4840d08f1027f797bc628d57a Mon Sep 17 00:00:00 2001 From: JDM170 <30170278+JDM170@users.noreply.github.com> Date: Mon, 28 Sep 2020 22:39:59 +0700 Subject: [PATCH] Code changes, added base64 proj on c++ Signed-off-by: JDM170 <30170278+JDM170@users.noreply.github.com> --- Program.cs | 131 +++++++++++++++++++++++----- base64/base64.cbp | 51 +++++++++++ base64/base64.cpp | 93 ++++++++++++++++++++ base64/base64.depend | 17 ++++ base64/base64.h | 11 +++ base64/base64.layout | 20 +++++ base64/main.cpp | 37 ++++++++ base64/main.h | 30 +++++++ model_coder.csproj | 4 + tea.cs | 63 +++++++------- test/partial_file_encode.enc | Bin 1374364 -> 1374364 bytes utils.cs | 160 ++++++++++++++++++++++++++++++----- 12 files changed, 548 insertions(+), 69 deletions(-) create mode 100644 base64/base64.cbp create mode 100644 base64/base64.cpp create mode 100644 base64/base64.depend create mode 100644 base64/base64.h create mode 100644 base64/base64.layout create mode 100644 base64/main.cpp create mode 100644 base64/main.h diff --git a/Program.cs b/Program.cs index ce35399..0ccb554 100644 --- a/Program.cs +++ b/Program.cs @@ -8,17 +8,49 @@ */ using System; using System.IO; +using System.Text; +using System.Runtime.InteropServices; +using System.Reflection; using Tea; using Utils; +public class dllimport +{ + Assembly asm = Assembly.LoadFrom(@".\base64.dll"); + + //public string test(string str) + //{ + // return Base64Encode(Encoding.UTF8.GetBytes(str), 8); + //} +} namespace ModelCoder { class Program { - private static readonly int encodeSize = 3000; + private static IUtil util; + private static ITeaCoding tea; + private static dllimport dlltest; + private static readonly uint blockSize = 12; + private static readonly uint blockNums = 3000; + private static readonly uint encodeSize = blockSize * blockNums; + private static string checkBlockBytes(byte block) + { + const int byteCount = 8; + string newBlock = block.ToString(); + int size = Encoding.UTF8.GetByteCount(newBlock); + //Console.WriteLine("newBlock: " + newBlock); + //Console.WriteLine("newBlock size: " + size); + if (size < byteCount) + for (int i = 0; i < (byteCount - size); i++) + newBlock += '\0'; + //Console.WriteLine("newblock size: " + System.Text.ASCIIEncoding.UTF8.GetByteCount(newBlock)); + return newBlock; + } + private static bool encodeFile(string path, uint[] key) { + #region Reading file Console.WriteLine("[OUTPUT] Reading: " + path); byte[] file_bytes; try { @@ -27,16 +59,70 @@ namespace ModelCoder Console.WriteLine("[OUTPUT] File '" + path + "' not found"); return false; } - - ITeaCoding tea = new TeaCoding(); - var block = new uint[2]; - for (uint i = 0; i < encodeSize; i += 2) { - Console.WriteLine(i + " start iteration"); - block[0] = file_bytes[i]; - block[1] = file_bytes[i + 1]; - Console.WriteLine(i + " start encoding"); - tea.code(block, key); + #endregion + + /*string[] test = {"22\0\0\0\0\0\0", "1\0\0\0\0\0\0\0"}; + foreach (var i in test) + { + Console.WriteLine(i + " bytes: " + Encoding.UTF8.GetByteCount(i)); + Console.WriteLine(i + " b64: " + util.Base64Encode(i)); } + string blockCheck = checkBlockBytes(file_bytes[0]); + Console.WriteLine("first file block: " + blockCheck); + Console.WriteLine("first file block size: " + Encoding.UTF8.GetByteCount(blockCheck)); + blockCheck = util.Base64Encode(blockCheck); + Console.WriteLine("first file block b64e: " + blockCheck); + Console.WriteLine("first file block b64d: " + util.Base64Decode(blockCheck));*/ + + // TEA and Base64 encoding + var block = new uint[2]; + string result = ""; + for (uint i = 0; i < 10; i += 2) + { + block[0] = Convert.ToUInt32(checkBlockBytes(file_bytes[i])); + block[1] = Convert.ToUInt32(checkBlockBytes(file_bytes[i + 1])); + + Console.WriteLine("st block0: " + block[0]); + Console.WriteLine("st block1: " + block[1]); + + tea.encode(block, key); + + Console.WriteLine("enc block0: " + block[0]); + Console.WriteLine("enc block1: " + block[1]); + + Console.WriteLine("block0 bytes:"); + foreach (var j in BitConverter.GetBytes(block[0])) + Console.WriteLine(" " + j); + + Console.WriteLine("block1 bytes:"); + foreach (var j in BitConverter.GetBytes(block[1])) + Console.WriteLine(" " + j); + + Console.WriteLine(util.Base64Encode(block[0].ToString())); + Console.WriteLine(util.Base64Encode(block[1].ToString())); + + Console.WriteLine(); + + //result += util.Base64Encode(BitConverter.GetBytes(block[0])) + + // util.Base64Encode(BitConverter.GetBytes(block[1])); + result += util.Base64Encode(block[0].ToString()) + + util.Base64Encode(block[1].ToString()); + } + Console.WriteLine("Result: " + result); + Console.WriteLine("[OUTPUT] File '" + path + "' has been TEA and Base64 encoded"); + + #region Writing file with encoded and non-encoded part + string encodedPath = path + ".enc"; + // encoded part + File.WriteAllText(encodedPath, result); + // non-encoded part + FileStream ofile = File.OpenWrite(encodedPath); + ofile.Seek(encodeSize, 0); + for (uint i = blockNums; i < file_bytes.Length; i++) + ofile.WriteByte(file_bytes[i]); + ofile.Close(); + Console.WriteLine("[OUTPUT] File '" + encodedPath + "' successfully written"); + #endregion return true; } @@ -44,28 +130,31 @@ namespace ModelCoder [STAThread] static void Main(string[] args) { - IUtil util = new Util(); + util = new Util(); + tea = new TeaCoding(); + dlltest = new dllimport(); + //Console.WriteLine(dlltest.test("22")); string fpath; - if (args.Length > 0) { + if (args.Length > 0) fpath = args[0]; - } else { - Console.WriteLine("[OUTPUT] You can open file(s) with this program"); - Console.WriteLine("[OUTPUT] Or drag'n'drop on it"); - Console.Write("[INPUT] Enter filename (without spaces): "); - fpath = Console.ReadLine(); + else + { + Console.WriteLine("[OUTPUT] You can open file(s) with this program"); + Console.WriteLine("[OUTPUT] Or drag'n'drop on it"); + Console.Write("[INPUT] Enter filename (without spaces): "); + fpath = Console.ReadLine(); } Console.Write("[INPUT] Enter key: "); uint[] uKey = util.ConvertKey(Console.ReadLine()); - + Console.WriteLine("[OUTPUT] Reading file(s)..."); - if (args.Length > 1) { + if (args.Length > 0) foreach (string i in args) encodeFile(i, uKey); - } else { + else encodeFile(fpath, uKey); - } Console.Write("Press any key to continue . . . "); Console.ReadKey(true); diff --git a/base64/base64.cbp b/base64/base64.cbp new file mode 100644 index 0000000..f7a0e06 --- /dev/null +++ b/base64/base64.cbp @@ -0,0 +1,51 @@ + + + + + + diff --git a/base64/base64.cpp b/base64/base64.cpp new file mode 100644 index 0000000..fe33a06 --- /dev/null +++ b/base64/base64.cpp @@ -0,0 +1,93 @@ +#include "base64.h" +#include + +static const std::string base64_chars = + "ABCDEFGHIJKLMNOPQRSTUVWXYZ" + "abcdefghijklmnopqrstuvwxyz" + "0123456789+/"; + + +static inline bool is_base64(BYTE c) { + return (isalnum(c) || (c == '+') || (c == '/')); +} + +std::string base64encode(BYTE const* buf, unsigned int bufLen) { + std::string ret; + int i = 0, j = 0; + BYTE char_array_3[3], char_array_4[4]; + + while(bufLen--) { + char_array_3[i++] = *(buf++); + if(i == 3) { + char_array_4[0] = (char_array_3[0] & 0xfc) >> 2; + char_array_4[1] = ((char_array_3[0] & 0x03) << 4) + ((char_array_3[1] & 0xf0) >> 4); + char_array_4[2] = ((char_array_3[1] & 0x0f) << 2) + ((char_array_3[2] & 0xc0) >> 6); + char_array_4[3] = char_array_3[2] & 0x3f; + + for(i = 0; i < 4; i++) + ret += base64_chars[char_array_4[i]]; + i = 0; + } + } + + if(i) { + for(j = i; j < 3; j++) + char_array_3[j] = '\0'; + + char_array_4[0] = (char_array_3[0] & 0xfc) >> 2; + char_array_4[1] = ((char_array_3[0] & 0x03) << 4) + ((char_array_3[1] & 0xf0) >> 4); + char_array_4[2] = ((char_array_3[1] & 0x0f) << 2) + ((char_array_3[2] & 0xc0) >> 6); + char_array_4[3] = char_array_3[2] & 0x3f; + + for(j = 0; j < (i + 1); j++) + ret += base64_chars[char_array_4[j]]; + + while(i++ < 3) + ret += '='; + } + + return ret; +} + +std::vector base64decode(std::string const& encoded_string) { + int in_len = encoded_string.size(), + i = 0, + j = 0, + in_ = 0; + BYTE char_array_4[4], char_array_3[3]; + std::vector ret; + + while(in_len-- && (encoded_string[in_] != '=') && is_base64(encoded_string[in_])) { + char_array_4[i++] = encoded_string[in_]; + in_++; + if(i == 4) { + for(i = 0; i < 4; i++) + char_array_4[i] = base64_chars.find(char_array_4[i]); + + char_array_3[0] = (char_array_4[0] << 2) + ((char_array_4[1] & 0x30) >> 4); + char_array_3[1] = ((char_array_4[1] & 0xf) << 4) + ((char_array_4[2] & 0x3c) >> 2); + char_array_3[2] = ((char_array_4[2] & 0x3) << 6) + char_array_4[3]; + + for(i = 0; i < 3; i++) + ret.push_back(char_array_3[i]); + i = 0; + } + } + + if(i) { + for(j = i; j < 4; j++) + char_array_4[j] = 0; + + for(j = 0; j < 4; j++) + char_array_4[j] = base64_chars.find(char_array_4[j]); + + char_array_3[0] = (char_array_4[0] << 2) + ((char_array_4[1] & 0x30) >> 4); + char_array_3[1] = ((char_array_4[1] & 0xf) << 4) + ((char_array_4[2] & 0x3c) >> 2); + char_array_3[2] = ((char_array_4[2] & 0x3) << 6) + char_array_4[3]; + + for(j = 0; j < (i - 1); j++) + ret.push_back(char_array_3[j]); + } + + return ret; +} diff --git a/base64/base64.depend b/base64/base64.depend new file mode 100644 index 0000000..ff9fab4 --- /dev/null +++ b/base64/base64.depend @@ -0,0 +1,17 @@ +# depslib dependency file v1.0 +1600530854 source:c:\users\jdm17\desktop\base64\base64.cpp + "base64.h" + + +1600530854 c:\users\jdm17\desktop\base64\base64.h + + + +1601296249 source:c:\users\jdm17\desktop\base64\main.cpp + "main.h" + "base64.h" + +1601297599 c:\users\jdm17\desktop\base64\main.h + + + diff --git a/base64/base64.h b/base64/base64.h new file mode 100644 index 0000000..ee962ea --- /dev/null +++ b/base64/base64.h @@ -0,0 +1,11 @@ +#ifndef _BASE64_H_ +#define _BASE64_H_ + +#include +#include +typedef unsigned char BYTE; + +std::string base64encode(BYTE const*, unsigned int); +std::vector base64decode(std::string const&); + +#endif diff --git a/base64/base64.layout b/base64/base64.layout new file mode 100644 index 0000000..63fe404 --- /dev/null +++ b/base64/base64.layout @@ -0,0 +1,20 @@ + + + + + + + + + + + + + + + + + + + + diff --git a/base64/main.cpp b/base64/main.cpp new file mode 100644 index 0000000..1348167 --- /dev/null +++ b/base64/main.cpp @@ -0,0 +1,37 @@ +#include "main.h" +#include "base64.h" + +// a sample exported function +void DLL_EXPORT SomeFunction(const LPCSTR sometext) +{ + MessageBoxA(0, sometext, "DLL Message", MB_OK | MB_ICONINFORMATION); +} + +extern "C" DLL_EXPORT std::string Base64Encode(BYTE const* buf, unsigned int bufLen) +{ + return base64encode(buf, bufLen); +} + +extern "C" DLL_EXPORT BOOL APIENTRY DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved) +{ + switch (fdwReason) + { + case DLL_PROCESS_ATTACH: + // attach to process + // return FALSE to fail DLL load + break; + + case DLL_PROCESS_DETACH: + // detach from process + break; + + case DLL_THREAD_ATTACH: + // attach to thread + break; + + case DLL_THREAD_DETACH: + // detach from thread + break; + } + return TRUE; // succesful +} diff --git a/base64/main.h b/base64/main.h new file mode 100644 index 0000000..4140454 --- /dev/null +++ b/base64/main.h @@ -0,0 +1,30 @@ +#ifndef __MAIN_H__ +#define __MAIN_H__ + +#include + +/* To use this exported function of dll, include this header + * in your project. + */ + +#ifdef BUILD_DLL + #define DLL_EXPORT __declspec(dllexport) +#else + #define DLL_EXPORT __declspec(dllimport) +#endif + + +#ifdef __cplusplus +extern "C" +{ +#endif + +//#include +void DLL_EXPORT SomeFunction(const LPCSTR sometext); +//std::string DLL_EXPORT Base64Encode(unsigned char const* buf, unsigned int bufLen); + +#ifdef __cplusplus +} +#endif + +#endif // __MAIN_H__ diff --git a/model_coder.csproj b/model_coder.csproj index 27d88f3..9dd7531 100644 --- a/model_coder.csproj +++ b/model_coder.csproj @@ -48,6 +48,10 @@ TRACE + + base64.dll + True + 4.0 diff --git a/tea.cs b/tea.cs index fb54fa0..dc27678 100644 --- a/tea.cs +++ b/tea.cs @@ -12,62 +12,67 @@ namespace Tea { public interface ITeaCoding { - void code(uint[] v, uint[] k); + void encode(uint[] v, uint[] k); //void decode(uint[] v, uint[] k); } public partial class TeaCoding: ITeaCoding { private readonly uint c_delta = 0x9E3779B9; - /* + public void encode(uint[] v, uint[] k) { uint v0 = v[0], v1 = v[1]; uint sum = 0; - //for(int i = 0; i < 32; i++) { - for(uint i = 32; i > 0; i--) { - //v0 += (((v1 << 4) ^ (v1 >> 5)) + v1) ^ (sum + k[sum & 3]); - //sum += c_delta; - //v1 += (((v0 << 4) ^ (v0 >> 5)) + v0) ^ (sum + k[(sum >> 11) & 3]); - + for (int i = 0; i < 32; i++) { + //for (uint i = 32; i > 0; i--) { + unchecked { + v0 += (((v1 << 4) ^ (v1 >> 5)) + v1) ^ (sum + k[sum & 3]); + sum += c_delta; + v1 += (((v0 << 4) ^ (v0 >> 5)) + v0) ^ (sum + k[(sum >> 11) & 3]); + } //sum += c_delta; //v0 += (v1 << 4) + k[0] ^ v1 + sum ^ (v1 >> 5) + k[1]; //v1 += (v0 << 4) + k[2] ^ v0 + sum ^ (v0 >> 5) + k[3]; - v0 += (v1 << 4 ^ v1 >> 5) + v1 ^ sum + k[sum & 3]; - sum += c_delta; - v1 += (v0 << 4 ^ v0 >> 5) + v0 ^ sum + k[sum >> 11 & 3]; + //v0 += (v1 << 4 ^ v1 >> 5) + v1 ^ sum + k[sum & 3]; + //sum += c_delta; + //v1 += (v0 << 4 ^ v0 >> 5) + v0 ^ sum + k[sum >> 11 & 3]; } v[0] = v0; v[1] = v1; } - */ - public void code(uint[] v, uint[] k) + /* + public void encode(uint[] v, uint[] k) { - uint y = v[0]; - uint z = v[1]; - uint sum = 0; - uint n = 32; + uint y = v[0]; + uint z = v[1]; + uint sum = 0; + uint n = 32; - while (n-- > 0) - { - y += (z << 4 ^ z >> 5) + z ^ sum + k[sum & 3]; - sum += c_delta; - z += (y << 4 ^ y >> 5) + y ^ sum + k[sum >> 11 & 3]; - } + unchecked { + while (n-- > 0) + { + y += (z << 4 ^ z >> 5) + z ^ sum + k[sum & 3]; + sum += c_delta; + z += (y << 4 ^ y >> 5) + y ^ sum + k[sum >> 11 & 3]; + } + } - v[0] = y; - v[1] = z; + v[0] = y; + v[1] = z; } - + */ /* private readonly uint c_sum = 0xC6EF3720; public void decode(uint[] v, uint[] k) { uint v0 = v[0], v1 = v[1]; uint sum = c_sum; for (int i = 0; i < 32; i++) { - v1 -= (((v0 << 4) ^ (v0 >> 5)) + v0) ^ (sum + k[(sum >> 11) & 3]); - sum -= c_delta; - v0 -= (((v1 << 4) ^ (v1 >> 5)) + v1) ^ (sum + k[sum & 3]); + unchecked { + v1 -= (((v0 << 4) ^ (v0 >> 5)) + v0) ^ (sum + k[(sum >> 11) & 3]); + sum -= c_delta; + v0 -= (((v1 << 4) ^ (v1 >> 5)) + v1) ^ (sum + k[sum & 3]); + } } v[0] = v0; v[1] = v1; diff --git a/test/partial_file_encode.enc b/test/partial_file_encode.enc index 0eaa28a73dcb998ea71a0694238348ed981c95dc..f166b4f3930d0b472b526411325e9354af534bc8 100644 GIT binary patch delta 160 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 8) & 0xFF)); - output.Append((char)((input >> 16) & 0xFF)); - output.Append((char)((input >> 24) & 0xFF)); - return output.ToString(); + var output = new StringBuilder(); + output.Append((char)((input & 0xFF))); + output.Append((char)((input >> 8) & 0xFF)); + output.Append((char)((input >> 16) & 0xFF)); + output.Append((char)((input >> 24) & 0xFF)); + return output.ToString(); } + #endregion + #region Base64 encoding/decoding + public string Base64Encode(string plainText) + { + var plainTextBytes = Encoding.UTF8.GetBytes(plainText); + return Convert.ToBase64String(plainTextBytes); + } + /*public string Base64Encode(byte[] data) + return Convert.ToBase64String(data); + public char[] Base64Encode(byte[] data) + { + int length, length2; + int blockCount; + int paddingCount; + + length = data.Length; + + if ((length % 3) == 0) + { + paddingCount = 0; + blockCount = length / 3; + } + else + { + paddingCount = 3 - (length % 3); + blockCount = (length + paddingCount) / 3; + } + + length2 = length + paddingCount; + + Console.WriteLine("length: " + length); + Console.WriteLine("length2: " + length2); + Console.WriteLine("blockCount: " + blockCount); + Console.WriteLine("paddingCount: " + paddingCount); + + byte[] source2; + source2 = new byte[length2]; + + for (int x = 0; x < length2; x++) + source2[x] = x < length ? data[x] : (byte)0; + + byte b1, b2, b3; + byte temp, temp1, temp2, temp3, temp4; + var buffer = new byte[blockCount * 4]; + var result = new char[blockCount * 4]; + + for (int x = 0; x < blockCount; x++) + { + b1 = source2[x * 3]; + b2 = source2[x * 3 + 1]; + b3 = source2[x * 3 + 2]; + + temp1 = (byte)((b1 & 252) >> 2); + + temp = (byte)((b1 & 3) << 4); + temp2 = (byte)((b2 & 240) >> 4); + temp2 += temp; + + temp = (byte)((b2 & 15) << 2); + temp3 = (byte)((b3 & 192) >> 6); + temp3 += temp; + + temp4 = (byte)(b3 & 63); + + buffer[x * 4] = temp1; + buffer[x * 4 + 1] = temp2; + buffer[x * 4 + 2] = temp3; + buffer[x * 4 + 3] = temp4; + } + + for (int x = 0; x < blockCount * 4; x++) + result[x] = SixBitToChar(buffer[x]); + + switch (paddingCount) + { + case 0: + break; + case 1: + result[blockCount * 4 - 1] = '='; + break; + case 2: + result[blockCount * 4 - 1] = '='; + result[blockCount * 4 - 2] = '='; + break; + default: + break; + } + + return result; + } + private static char SixBitToChar(byte b) + { + var lookupTable = new char[64] { + 'A','B','C','D','E','F','G','H','I','J','K','L','M', + 'N','O','P','Q','R','S','T','U','V','W','X','Y','Z', + 'a','b','c','d','e','f','g','h','i','j','k','l','m', + 'n','o','p','q','r','s','t','u','v','w','x','y','z', + '0','1','2','3','4','5','6','7','8','9','+','/' + }; + + if ((b >= 0) && (b <= 63)) + { + return lookupTable[(int)b]; + } + else + { + return ' '; + } + }*/ + + public string Base64Decode(string base64EncodedData) + { + var base64EncodedBytes = Convert.FromBase64String(base64EncodedData); + return Encoding.UTF8.GetString(base64EncodedBytes); + } + #endregion } }