From b90e610327427d0f3539841970feadeb46255d75 Mon Sep 17 00:00:00 2001 From: Godwin Asuquo Date: Wed, 2 Feb 2022 13:57:26 +0100 Subject: [PATCH 1/5] fix red indicator for XMR nodes --- cw_core/lib/node.dart | 36 +++++++++++++----------------------- 1 file changed, 13 insertions(+), 23 deletions(-) diff --git a/cw_core/lib/node.dart b/cw_core/lib/node.dart index c9282c6e7..3dc876521 100644 --- a/cw_core/lib/node.dart +++ b/cw_core/lib/node.dart @@ -95,29 +95,19 @@ class Node extends HiveObject with Keyable { } Future requestMoneroNode() async { - return false; - //try { - // Map resBody; - - // if (login != null && password != null) { - // final digestRequest = DigestRequest(); - // final response = await digestRequest.request( - // uri: uri.toString(), login: login, password: password); - // resBody = response.data as Map; - // } else { - // final rpcUri = Uri.http(uri.authority, '/json_rpc'); - // final headers = {'Content-type': 'application/json'}; - // final body = - // json.encode({'jsonrpc': '2.0', 'id': '0', 'method': 'get_info'}); - // final response = - // await http.post(rpcUri.toString(), headers: headers, body: body); - // resBody = json.decode(response.body) as Map; - // } - - // return !(resBody['result']['offline'] as bool); - //} catch (_) { - // return false; - //} + try { + Map resBody; + final rpcUri = Uri.http(uri.authority, '/json_rpc'); + final headers = {'Content-type': 'application/json'}; + final body = + json.encode({'jsonrpc': '2.0', 'id': '0', 'method': 'get_info'}); + final response = + await http.post(rpcUri.toString(), headers: headers, body: body); + resBody = json.decode(response.body) as Map; + return !(resBody['result']['offline'] as bool); + } catch (_) { + return false; + } } Future requestElectrumServer() async { From 9e1753539f0161d97a41e7e31193d60cca1918e3 Mon Sep 17 00:00:00 2001 From: Godwin Asuquo Date: Wed, 2 Feb 2022 15:36:18 +0100 Subject: [PATCH 2/5] implement Digest Auth --- cw_core/lib/digest_auth.dart | 41 ++++++++++++++++++++++++++++++++++++ cw_core/lib/node.dart | 20 +++++++----------- 2 files changed, 49 insertions(+), 12 deletions(-) create mode 100644 cw_core/lib/digest_auth.dart diff --git a/cw_core/lib/digest_auth.dart b/cw_core/lib/digest_auth.dart new file mode 100644 index 000000000..752ff0779 --- /dev/null +++ b/cw_core/lib/digest_auth.dart @@ -0,0 +1,41 @@ +import 'dart:convert'; +import 'dart:io'; + +import 'package:http/http.dart' as http; +import 'package:http/io_client.dart' as ioc; + +class DigestAuth{ + Futurerequest({ + String uri, + String login = "", + String password = "", + }) async { + final path = '/json_rpc'; + final rpcUri = Uri.http(uri, path); + final realm = 'monero-rpc'; + final postMap = { + 'jsonrpc': '2.0', + 'id': '0', + 'method': 'get_info' + }; + final authenticatingClient = HttpClient(); + + authenticatingClient.addCredentials( + rpcUri, + realm, + HttpClientDigestCredentials(login ?? "", password ?? ""), + ); + + final http.Client client = ioc.IOClient(authenticatingClient); + + final response = await client.post( + rpcUri, + headers: {'Content-Type': 'application/json'}, + body: json.encode(postMap), + ); + + client.close(); + + return response; + } +} \ No newline at end of file diff --git a/cw_core/lib/node.dart b/cw_core/lib/node.dart index 3dc876521..f7f24d89b 100644 --- a/cw_core/lib/node.dart +++ b/cw_core/lib/node.dart @@ -1,5 +1,6 @@ import 'dart:io'; +import 'package:cw_core/digest_auth.dart'; import 'package:cw_core/keyable.dart'; import 'package:flutter/foundation.dart'; import 'dart:convert'; @@ -95,20 +96,15 @@ class Node extends HiveObject with Keyable { } Future requestMoneroNode() async { - try { - Map resBody; - final rpcUri = Uri.http(uri.authority, '/json_rpc'); - final headers = {'Content-type': 'application/json'}; - final body = - json.encode({'jsonrpc': '2.0', 'id': '0', 'method': 'get_info'}); - final response = - await http.post(rpcUri.toString(), headers: headers, body: body); - resBody = json.decode(response.body) as Map; - return !(resBody['result']['offline'] as bool); - } catch (_) { + final digestAuth = DigestAuth(); + try { + final response = await digestAuth.request(uri: uri.authority, login: login, password: password); + final resBody = json.decode(response.body) as Map; + return !(resBody['result']['offline'] as bool); + } catch (_) { return false; } - } +} Future requestElectrumServer() async { try { From 1bc5dd9e468acbe1b73b383d905c94f3c1b9640c Mon Sep 17 00:00:00 2001 From: Godwin Asuquo Date: Thu, 3 Feb 2022 11:16:24 +0100 Subject: [PATCH 3/5] fix issues from code review --- cw_core/lib/digest_auth.dart | 41 ------------------------------------ cw_core/lib/node.dart | 31 ++++++++++++++++++++++++--- 2 files changed, 28 insertions(+), 44 deletions(-) delete mode 100644 cw_core/lib/digest_auth.dart diff --git a/cw_core/lib/digest_auth.dart b/cw_core/lib/digest_auth.dart deleted file mode 100644 index 752ff0779..000000000 --- a/cw_core/lib/digest_auth.dart +++ /dev/null @@ -1,41 +0,0 @@ -import 'dart:convert'; -import 'dart:io'; - -import 'package:http/http.dart' as http; -import 'package:http/io_client.dart' as ioc; - -class DigestAuth{ - Futurerequest({ - String uri, - String login = "", - String password = "", - }) async { - final path = '/json_rpc'; - final rpcUri = Uri.http(uri, path); - final realm = 'monero-rpc'; - final postMap = { - 'jsonrpc': '2.0', - 'id': '0', - 'method': 'get_info' - }; - final authenticatingClient = HttpClient(); - - authenticatingClient.addCredentials( - rpcUri, - realm, - HttpClientDigestCredentials(login ?? "", password ?? ""), - ); - - final http.Client client = ioc.IOClient(authenticatingClient); - - final response = await client.post( - rpcUri, - headers: {'Content-Type': 'application/json'}, - body: json.encode(postMap), - ); - - client.close(); - - return response; - } -} \ No newline at end of file diff --git a/cw_core/lib/node.dart b/cw_core/lib/node.dart index f7f24d89b..1bb717243 100644 --- a/cw_core/lib/node.dart +++ b/cw_core/lib/node.dart @@ -1,12 +1,12 @@ import 'dart:io'; -import 'package:cw_core/digest_auth.dart'; import 'package:cw_core/keyable.dart'; import 'package:flutter/foundation.dart'; import 'dart:convert'; import 'package:http/http.dart' as http; import 'package:hive/hive.dart'; import 'package:cw_core/wallet_type.dart'; +import 'package:http/io_client.dart' as ioc; //import 'package:cake_wallet/entities/digest_request.dart'; part 'node.g.dart'; @@ -96,9 +96,34 @@ class Node extends HiveObject with Keyable { } Future requestMoneroNode() async { - final digestAuth = DigestAuth(); + try { - final response = await digestAuth.request(uri: uri.authority, login: login, password: password); + final path = '/json_rpc'; + final rpcUri = isSSL ? Uri.https(uri.authority, path) : Uri.http(uri.authority, path); + final realm = 'monero-rpc'; + final body = { + 'jsonrpc': '2.0', + 'id': '0', + 'method': 'get_info' + }; + final authenticatingClient = HttpClient(); + + authenticatingClient.addCredentials( + rpcUri, + realm, + HttpClientDigestCredentials(login ?? '', password ?? ''), + ); + + final http.Client client = ioc.IOClient(authenticatingClient); + + final response = await client.post( + rpcUri, + headers: {'Content-Type': 'application/json'}, + body: json.encode(body), + ); + + client.close(); + final resBody = json.decode(response.body) as Map; return !(resBody['result']['offline'] as bool); } catch (_) { From c162e34ef4a024dc046a4f6fcdacc9a3e0f855f8 Mon Sep 17 00:00:00 2001 From: Godwin Asuquo Date: Thu, 3 Feb 2022 11:23:22 +0100 Subject: [PATCH 4/5] remove unused code --- cw_core/lib/node.dart | 17 +++--- lib/entities/digest_request.dart | 96 -------------------------------- 2 files changed, 9 insertions(+), 104 deletions(-) delete mode 100644 lib/entities/digest_request.dart diff --git a/cw_core/lib/node.dart b/cw_core/lib/node.dart index 1bb717243..acf41dd9a 100644 --- a/cw_core/lib/node.dart +++ b/cw_core/lib/node.dart @@ -97,15 +97,16 @@ class Node extends HiveObject with Keyable { Future requestMoneroNode() async { - try { - final path = '/json_rpc'; - final rpcUri = isSSL ? Uri.https(uri.authority, path) : Uri.http(uri.authority, path); - final realm = 'monero-rpc'; - final body = { + final path = '/json_rpc'; + final rpcUri = isSSL ? Uri.https(uri.authority, path) : Uri.http(uri.authority, path); + final realm = 'monero-rpc'; + final body = { 'jsonrpc': '2.0', 'id': '0', 'method': 'get_info' - }; + }; + + try { final authenticatingClient = HttpClient(); authenticatingClient.addCredentials( @@ -127,8 +128,8 @@ class Node extends HiveObject with Keyable { final resBody = json.decode(response.body) as Map; return !(resBody['result']['offline'] as bool); } catch (_) { - return false; - } + return false; + } } Future requestElectrumServer() async { diff --git a/lib/entities/digest_request.dart b/lib/entities/digest_request.dart deleted file mode 100644 index 4f4be1c95..000000000 --- a/lib/entities/digest_request.dart +++ /dev/null @@ -1,96 +0,0 @@ -import 'dart:convert'; -import 'package:dio/dio.dart' as __dio; -import 'package:crypto/crypto.dart' as crypto; -import 'dart:math' as math; - -class DigestRequest { - final md5 = crypto.md5; - - String generateCnonce() { - final rnd = math.Random.secure(); - final values = List.generate(32, (i) => rnd.nextInt(256)); - return base64Url.encode(values).substring(0, 8); - } - - String generateHA1({String realm, String username, String password}) { - final ha1CredentialsData = - Utf8Encoder().convert('$username:$realm:$password'); - final ha1 = md5.convert(ha1CredentialsData).toString(); - - return ha1; - } - - String generateHA2({String method, String uri}) { - final ha2Data = Utf8Encoder().convert('$method:$uri'); - final ha2 = md5.convert(ha2Data).toString(); - - return ha2; - } - - String generateResponseString( - {String ha1, - String ha2, - String nonce, - String nonceCount, - String cnonce, - String qop}) { - final responseData = - Utf8Encoder().convert('$ha1:$nonce:$nonceCount:$cnonce:$qop:$ha2'); - final response = md5.convert(responseData).toString(); - - return response; - } - - Map parsetAuthorizationHeader({String source}) { - final authHeaderParts = - source.substring(7).split(',').map((item) => item.trim()); - final authenticate = Map(); - - for (final part in authHeaderParts) { - final kv = part.split('='); - authenticate[kv[0]] = - kv.getRange(1, kv.length).join('=').replaceAll('"', ''); - } - - return authenticate; - } - - Future<__dio.Response> request( - {String uri, String login, String password}) async { - const path = '/json_rpc'; - const method = 'POST'; - final url = Uri.http(uri, path); - final dio = __dio.Dio(); - final headers = {'Content-type': 'application/json'}; - final body = - json.encode({"jsonrpc": "2.0", "id": "0", "method": "get_info"}); - final credentialsResponse = await dio.post(url.toString(), - options: __dio.Options(headers: headers, validateStatus: (_) => true)); - final authenticate = parsetAuthorizationHeader( - source: credentialsResponse.headers['www-authenticate'].first); - final qop = authenticate['qop']; - final algorithm = 'MD5'; - final realm = 'monero-rpc'; - final nonce = authenticate['nonce']; - final cnonce = generateCnonce(); - final nonceCount = '00000001'; - final ha1 = generateHA1(realm: realm, username: login, password: password); - final ha2 = generateHA2(method: method, uri: path); - final response = generateResponseString( - ha1: ha1, - ha2: ha2, - nonce: nonce, - nonceCount: nonceCount, - cnonce: cnonce, - qop: qop); - - final authorizationHeaders = { - 'Content-type': 'application/json', - 'Authorization': - 'Digest username="$login",realm="$realm",nonce="$nonce",uri="$path",algorithm="$algorithm",qop=$qop,nc=$nonceCount,cnonce="$cnonce",response="$response"' - }; - - return await dio.post(url.toString(), - options: __dio.Options(headers: authorizationHeaders), data: body); - } -} From aba7b6fc4513bc52a05d3cd585284215757bfbaf Mon Sep 17 00:00:00 2001 From: Godwin Asuquo Date: Thu, 3 Feb 2022 12:46:45 +0100 Subject: [PATCH 5/5] remove unused import --- cw_core/lib/node.dart | 63 +++++++++++++++++++++---------------------- 1 file changed, 31 insertions(+), 32 deletions(-) diff --git a/cw_core/lib/node.dart b/cw_core/lib/node.dart index acf41dd9a..ff1da7026 100644 --- a/cw_core/lib/node.dart +++ b/cw_core/lib/node.dart @@ -7,7 +7,6 @@ import 'package:http/http.dart' as http; import 'package:hive/hive.dart'; import 'package:cw_core/wallet_type.dart'; import 'package:http/io_client.dart' as ioc; -//import 'package:cake_wallet/entities/digest_request.dart'; part 'node.g.dart'; @@ -97,39 +96,39 @@ class Node extends HiveObject with Keyable { Future requestMoneroNode() async { - final path = '/json_rpc'; - final rpcUri = isSSL ? Uri.https(uri.authority, path) : Uri.http(uri.authority, path); - final realm = 'monero-rpc'; - final body = { - 'jsonrpc': '2.0', - 'id': '0', - 'method': 'get_info' - }; + final path = '/json_rpc'; + final rpcUri = isSSL ? Uri.https(uri.authority, path) : Uri.http(uri.authority, path); + final realm = 'monero-rpc'; + final body = { + 'jsonrpc': '2.0', + 'id': '0', + 'method': 'get_info' + }; - try { - final authenticatingClient = HttpClient(); - - authenticatingClient.addCredentials( - rpcUri, - realm, - HttpClientDigestCredentials(login ?? '', password ?? ''), - ); - - final http.Client client = ioc.IOClient(authenticatingClient); - - final response = await client.post( - rpcUri, - headers: {'Content-Type': 'application/json'}, - body: json.encode(body), - ); - - client.close(); + try { + final authenticatingClient = HttpClient(); + + authenticatingClient.addCredentials( + rpcUri, + realm, + HttpClientDigestCredentials(login ?? '', password ?? ''), + ); + + final http.Client client = ioc.IOClient(authenticatingClient); + + final response = await client.post( + rpcUri, + headers: {'Content-Type': 'application/json'}, + body: json.encode(body), + ); + + client.close(); - final resBody = json.decode(response.body) as Map; - return !(resBody['result']['offline'] as bool); - } catch (_) { - return false; - } + final resBody = json.decode(response.body) as Map; + return !(resBody['result']['offline'] as bool); + } catch (_) { + return false; + } } Future requestElectrumServer() async {