ws_bert_login.d 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286
  1. alias int8 = byte; // -128 — 127
  2. alias int16 = short; // -32768 — 32767
  3. alias int32 = int; // -2147483648 — 2147483647
  4. alias int64 = long; // -9223372036854775808 — 9223372036854775807
  5. alias uint8 = ubyte; // 0 — 255
  6. alias uint16 = ushort; // 0 — 65535
  7. alias uint32 = uint; // 0 — 4294967295
  8. alias uint64 = ulong; // 0 — 18446744073709551615
  9. alias f32 = float;
  10. alias f64 = double;
  11. // char '\xFF' unsigned 8 bit (UTF-8 code unit)
  12. // wchar '\uFFFF' unsigned 16 bit (UTF-16 code unit)
  13. // dchar '\U0000FFFF' unsigned 32 bit (UTF-32 code unit)
  14. import vibe.core.core;
  15. import vibe.http.router;
  16. import vibe.http.server;
  17. import vibe.http.fileserver;
  18. import vibe.http.websockets;
  19. import vibe.core.log;
  20. import std.stdio;
  21. import std.string;
  22. import std.array;
  23. import std.conv : to;
  24. import bert; // https://github.com/221V/dlang_erl_bert https://git.4dev.win/game1/dlang_erl_bert
  25. import secured.symmetric; // https://github.com/221V/SecureD // https://github.com/221V/js_AES256CBC
  26. import session;
  27. import mustache;
  28. alias MustacheEngine!(string) Mustache;
  29. string byte_arr_to_str(ubyte[] arr){
  30. string[] str_arr;
  31. foreach(elem; arr){
  32. str_arr ~= to!string(elem);
  33. }
  34. return "[" ~ str_arr.join(",") ~ "]";
  35. }
  36. ubyte[] str_to_byte_arr(string str_arr){
  37. str_arr = str_arr.replace("[", "").replace("]", "");
  38. string[] parts = str_arr.split(",");
  39. ubyte[] result;
  40. result.reserve(parts.length);
  41. foreach(part; parts){
  42. result ~= to!ubyte(part.strip());
  43. }
  44. return result;
  45. }
  46. void ws_bert_handle(scope WebSocket sock){
  47. //foreach(pair; req.headers.byKeyValue()){
  48. // writeln("Header: ", pair.key, " = ", pair.value);
  49. //}
  50. // simple echo server + :)
  51. //string client_id = req.attributes.get("client_id", "");
  52. //writeln("96 client_id = ", client_id);
  53. while(sock.connected){
  54. //auto msg = sock.receiveText();
  55. //sock.send(msg ~ " :)");
  56. auto msg = sock.receiveBinary();
  57. if(msg == "1"){
  58. sock.send("0"); // ws PING - PONG
  59. }else{
  60. writeln("Received: ", msg);
  61. auto decoder = new BertDecoder( cast(ubyte[])msg.dup );
  62. auto decoded = decoder.decode();
  63. msg_match(decoded, sock);
  64. }
  65. }
  66. // todo delete data in userSessions here
  67. }
  68. void msg_match(BertValue decoded, WebSocket sock){
  69. writeln("Decoded: ", decoded.toString());
  70. ubyte[] key;
  71. ubyte[] iv;
  72. if(decoded.type_ == BertType.Tuple){
  73. auto decoded1 = decoded.tupleValue;
  74. if(decoded1.length == 1){
  75. if(auto num1 = cast(uint8)decoded1[0].intValue){ // we can use js AES for additional password encrypt for login-logout // ws.send(enc(tuple( number(1) )));
  76. if(num1 == 1){ // init login -- get key + iv for encrypt password and send to server
  77. /*
  78. ubyte[] test_pass = cast(ubyte[])"12345678";
  79. SymmetricKey key = generateSymmetricKey( SymmetricAlgorithm.AES256_CBC );
  80. EncryptedData enc = encrypt(key, test_pass);
  81. //auto iv_hex = toHexString!(LetterCase.lower)(enc.iv);
  82. //auto encrypt = toHexString!(LetterCase.lower)(enc.cipherText);
  83. auto iv_hex = enc.iv;
  84. auto encrypt = enc.cipherText;
  85. writeln("Key: ", key.key);
  86. //writeln("Key: ", key.toString); // base64 encoded string
  87. //writeln("IV: ", toHexString!(LetterCase.lower)(enc.iv));
  88. writeln("IV: ", iv_hex);
  89. //writeln("Encrypt: ", enc);
  90. writeln("Encrypt: ", encrypt);
  91. */
  92. SymmetricKeyIV rand_key_iv = generateSymmetricKeyIV(); // default SymmetricAlgorithm.AES256_CBC
  93. writeln("rand key: ", rand_key_iv.key);
  94. writeln("rand iv: ", rand_key_iv.iv);
  95. string client_id = generateCookie();
  96. userSessions[client_id ~ "_key"] = rand_key_iv.key;
  97. userSessions[client_id ~ "_iv"] = rand_key_iv.iv;
  98. /*
  99. //auto test_pass = cast(ubyte[])"12345678";
  100. auto test_pass = cast(ubyte[])"12345678testтест";
  101. auto key = cast(ubyte[])[34, 74, 12, 214, 126, 234, 101, 147, 13, 32, 244, 185, 45, 217, 142, 33, 213, 116, 63, 179, 84, 23, 138, 187, 134, 130, 234, 54, 48, 66, 20, 152];
  102. auto iv = cast(ubyte[])[62, 133, 213, 219, 194, 200, 76, 142, 202, 16, 12, 237, 163, 147, 65, 93];
  103. auto encrypted = encrypt(key, iv, test_pass, SymmetricAlgorithm.AES256_CBC);
  104. writeln("Encrypted: ", encrypted.cipherText); // [223, 86, 210, 55, 192, 240, 144, 50, 159, 4, 238, 182, 171, 185, 80, 48] // [90, 85, 212, 32, 94, 33, 182, 43, 20, 183, 121, 59, 232, 45, 180, 158, 153, 9, 54, 45, 244, 32, 85, 24, 162, 206, 56, 235, 107, 194, 143, 192]
  105. //auto encrypted_data = cast(ubyte[])[223, 86, 210, 55, 192, 240, 144, 50, 159, 4, 238, 182, 171, 185, 80, 48];
  106. auto encrypted_data = cast(ubyte[])[90, 85, 212, 32, 94, 33, 182, 43, 20, 183, 121, 59, 232, 45, 180, 158, 153, 9, 54, 45, 244, 32, 85, 24, 162, 206, 56, 235, 107, 194, 143, 192];
  107. ubyte[] decrypted = decrypt(key, iv, encrypted_data, SymmetricAlgorithm.AES256_CBC);
  108. writeln("Decrypted: ", decrypted); // [49, 50, 51, 52, 53, 54, 55, 56] // [49, 50, 51, 52, 53, 54, 55, 56, 116, 101, 115, 116, 209, 130, 208, 181, 209, 129, 209, 130]
  109. writeln("Decrypted: ", cast(string)decrypted); // "12345678" // "12345678testтест"
  110. */
  111. sock.send("{window.key = new Uint8Array(" ~ byte_arr_to_str(rand_key_iv.key) ~ ");" ~
  112. "window.iv = new Uint8Array(" ~ byte_arr_to_str(rand_key_iv.iv) ~ ");" ~
  113. "window.uid = '" ~ client_id ~ "';" ~
  114. "do_log_in();}");
  115. /*
  116. ubyte[] key = sock.context.get("aes_key", "");
  117. ubyte[] iv = sock.context.get("aes_iv", "");
  118. if( key.empty || iv.empty ){}else{
  119. sock.send("{window.key = new Uint8Array(" ~ byte_arr_to_str(key) ~ ");" ~
  120. "window.iv = new Uint8Array(" ~ byte_arr_to_str(iv) ~ ");" ~
  121. "do_log_in();}");
  122. }
  123. */
  124. } // else do nothing
  125. } // else do nothing
  126. }else if(decoded1.length == 4){ // {2, "uid", "login", "encrypted_pass"}
  127. if(auto code2 = cast(uint8)decoded1[0].intValue){ // 2
  128. if(code2 == 2){
  129. if(auto client_id = cast(string)decoded1[1].binaryValue){
  130. writeln("client_id = ", client_id);
  131. if(auto login_str = cast(string)decoded1[2].binaryValue){
  132. writeln("login_str = ", login_str);
  133. if(auto maybe_encrypted_pass = cast(string)decoded1[3].binaryValue){
  134. writeln("maybe_encrypted_pass = ", maybe_encrypted_pass, " ", typeof(maybe_encrypted_pass).stringof); // Decoded: {2, <<116,101,115,116,49>>, <<91,49,50,53,44,50,51,54,44,50,50,48,44,50,53,53,44,49,50,48,44,49,54,57,44,49,56,51,44,49,48,50,44,50,49,49,44,51,53,44,50,52,54,44,50,49,55,44,55,49,44,50,54,44,50,49,50,44,56,56,93>>} // maybe_encoded_pass = [125,236,220,255,120,169,183,102,211,35,246,217,71,26,212,88] string
  135. //sock.send("{console.log('" ~ str1 ~ " la-la-la" ~ "')}"); //
  136. try{
  137. auto encrypted_pass = str_to_byte_arr(maybe_encrypted_pass);
  138. writeln("encoded_pass = ", encrypted_pass);
  139. if( (client_id ~ "_key") in userSessions){
  140. key = userSessions[client_id ~ "_key"];
  141. }
  142. if( (client_id ~ "_iv") in userSessions){
  143. iv = userSessions[client_id ~ "_iv"];
  144. }
  145. writeln("key = ", key);
  146. writeln("iv = ", iv);
  147. ubyte[] pass = decrypt(key, iv, encrypted_pass, SymmetricAlgorithm.AES256_CBC);
  148. writeln("Decrypted: ", pass); // byte array
  149. writeln("Decrypted: ", cast(string)pass); // string
  150. }catch(Exception e){} // skip err, do nothing
  151. }
  152. } // else do nothing
  153. } // else do nothing
  154. } // else do nothing
  155. } // else do nothing
  156. }else if(decoded1.length == 3){
  157. if(auto num1 = cast(uint8)decoded1[0].intValue){
  158. writeln("num1 = ", num1, " ", typeof(num1).stringof); // ws.send(enc(tuple( number(1), number(42), number(777) ))); // Decoded: {1, 42, 777} // num1 = 1 ubyte
  159. sock.send("{console.log(" ~ to!string(num1 + 42) ~ ")}"); // got 43 in browser console
  160. } // else do nothing
  161. if(auto str1 = cast(string)decoded1[1].binaryValue){
  162. writeln("str1 = ", str1, " ", typeof(str1).stringof); // ws.send(enc(tuple( number(1), bin('blabla'), number(777) ))); // Decoded: {1, <<98,108,97,98,108,97>>, 777} // str1 = blabla string
  163. sock.send("{console.log('" ~ str1 ~ " la-la-la" ~ "')}"); // got 'blabla la-la-la' in browser console
  164. } // else do nothing
  165. // var big_value = bigInt("61196067033413");
  166. // ws.send(enc(tuple( number(1), bin('9'), bignum( big_value ) ))); // got as long for auto
  167. if(decoded1[2].type_ == BertType.Int){
  168. if(auto num3 = decoded1[2].intValue){
  169. writeln("num3 = ", num3, " ", typeof(num3).stringof); // ws.send(enc(tuple( number(1), bin('9'), number(1) ))); // Decoded: {1, <<57>>, 1} // num3 = 1 long
  170. } // else do nothing
  171. } // else do nothing
  172. // var big_value = bigInt("6119606703341361196067033413");
  173. // ws.send(enc(tuple( number(1), bin('9'), bignum( big_value ) ))); // got as BigInt
  174. if(decoded1[2].type_ == BertType.BigInt){
  175. if(auto num3b = decoded1[2].bigintValue){
  176. writeln("num3b = ", num3b, " ", typeof(num3b).stringof); // Decoded: {1, <<57>>, 6119606703341361196067033413} // num3b = 6119606703341361196067033413 BigInt
  177. } // else do nothing
  178. } // else do nothing
  179. if(decoded1[2].type_ == BertType.List){
  180. auto list1 = decoded1[2].listValue; // ws.send(enc(tuple( number(1), bin('blabla'), list( number(1), number(2), number(3) ) ))); // Decoded: {1, <<98,108,97,98,108,97>>, [1, 2, 3]}
  181. if(list1.length == 3){
  182. //if(auto num31 = cast(uint32)list1[0].intValue){
  183. if(auto num31 = list1[0].intValue){
  184. writeln("num31 = ", num31, " ", typeof(num31).stringof); // ws.send(enc(tuple( number(1), bin('9'), list( number(1), number(2), number(3) ) ))); // Decoded: {1, <<57>>, [1, 2, 3]} // num31 = 1 uint
  185. sock.send("{console.log(" ~ to!string(num31 + 77) ~ ")}"); // got 78 in browser console
  186. } // else do nothing
  187. } // else do nothing
  188. } // else do nothing
  189. } // else do nothing
  190. } // else do nothing
  191. }
  192. void login_test(HTTPServerRequest req, HTTPServerResponse res){
  193. //string client_id = generateCookie();
  194. //req.context["client_id"] = client_id;
  195. Mustache mustache;
  196. auto context = new Mustache.Context;
  197. mustache.path = "priv";
  198. mustache.ext = "dtl";
  199. context["lang"] = "en";
  200. context["number1"] = 42;
  201. context.useSection("maybe1");
  202. context["part1"] = "<span>777</span>";
  203. context["result1"] = "Hello, World!\n";
  204. res.headers["Content-Type"] = "text/html; charset=utf-8";
  205. //res.writeBody("Hello, World!\n" ~ result);
  206. res.writeBody( mustache.render("login_test", context) );
  207. }