From c75b8cd3adaf686eeaf2cc106559664f33c66c7d Mon Sep 17 00:00:00 2001 From: Jeff Becker Date: Sun, 18 Feb 2018 10:12:38 -0500 Subject: [PATCH 1/9] fix famtool in openssl 1.1 --- famtool.cpp | 113 ++++++++++++++++++++++++---------------------------- 1 file changed, 52 insertions(+), 61 deletions(-) diff --git a/famtool.cpp b/famtool.cpp index 8e030e0..832f3f6 100644 --- a/famtool.cpp +++ b/famtool.cpp @@ -56,40 +56,31 @@ static std::shared_ptr LoadCertificate (const std::string& filename) if (family) family[0] = 0; } auto pkey = X509_get_pubkey (cert); - int keyType = EVP_PKEY_type(pkey->type); - switch (keyType) - { - case EVP_PKEY_EC: + + EC_KEY * ecKey = EVP_PKEY_get1_EC_KEY (pkey); + if (ecKey) + { + auto group = EC_KEY_get0_group (ecKey); + if (group) { - EC_KEY * ecKey = EVP_PKEY_get1_EC_KEY (pkey); - if (ecKey) + int curve = EC_GROUP_get_curve_name (group); + if (curve == NID_X9_62_prime256v1) { - auto group = EC_KEY_get0_group (ecKey); - if (group) - { - int curve = EC_GROUP_get_curve_name (group); - if (curve == NID_X9_62_prime256v1) - { - uint8_t signingKey[64]; - BIGNUM * x = BN_new(), * y = BN_new(); - EC_POINT_get_affine_coordinates_GFp (group, - EC_KEY_get0_public_key (ecKey), x, y, NULL); - bn2buf (x, signingKey, 32); - bn2buf (y, signingKey + 32, 32); - BN_free (x); BN_free (y); - verifier = std::make_shared(signingKey); - } - } - EC_KEY_free (ecKey); + uint8_t signingKey[64]; + BIGNUM * x = BN_new(), * y = BN_new(); + EC_POINT_get_affine_coordinates_GFp (group, + EC_KEY_get0_public_key (ecKey), x, y, NULL); + bn2buf (x, signingKey, 32); + bn2buf (y, signingKey + 32, 32); + BN_free (x); BN_free (y); + verifier = std::make_shared(signingKey); } } - - default: - break; + EC_KEY_free (ecKey); } EVP_PKEY_free (pkey); } - SSL_free (ssl); + SSL_free (ssl); } SSL_CTX_free (ctx); return verifier; @@ -100,44 +91,44 @@ static bool CreateFamilySignature (const std::string& family, const IdentHash& i SSL_CTX * ctx = SSL_CTX_new (TLSv1_method ()); int ret = SSL_CTX_use_PrivateKey_file (ctx, filename.c_str (), SSL_FILETYPE_PEM); if (ret) - { - SSL * ssl = SSL_new (ctx); - EVP_PKEY * pkey = SSL_get_privatekey (ssl); - EC_KEY * ecKey = EVP_PKEY_get1_EC_KEY (pkey); - if (ecKey) + { + SSL * ssl = SSL_new (ctx); + EVP_PKEY * pkey = SSL_get_privatekey (ssl); + EC_KEY * ecKey = EVP_PKEY_get1_EC_KEY (pkey); + if (ecKey) + { + auto group = EC_KEY_get0_group (ecKey); + if (group) + { + int curve = EC_GROUP_get_curve_name (group); + if (curve == NID_X9_62_prime256v1) { - auto group = EC_KEY_get0_group (ecKey); - if (group) - { - int curve = EC_GROUP_get_curve_name (group); - if (curve == NID_X9_62_prime256v1) - { - uint8_t signingPrivateKey[32], buf[50], signature[64]; - bn2buf (EC_KEY_get0_private_key (ecKey), signingPrivateKey, 32); - ECDSAP256Signer signer (signingPrivateKey); - size_t len = family.length (); - memcpy (buf, family.c_str (), len); - memcpy (buf + len, (const uint8_t *)ident, 32); - len += 32; - signer.Sign (buf, len, signature); - len = Base64EncodingBufferSize (64); - char * b64 = new char[len+1]; - len = ByteStreamToBase64 (signature, 64, b64, len); - b64[len] = 0; - sig = b64; - delete[] b64; - } - else - return false; - } - } - SSL_free (ssl); - } + uint8_t signingPrivateKey[32], buf[50], signature[64]; + bn2buf (EC_KEY_get0_private_key (ecKey), signingPrivateKey, 32); + ECDSAP256Signer signer (signingPrivateKey); + size_t len = family.length (); + memcpy (buf, family.c_str (), len); + memcpy (buf + len, (const uint8_t *)ident, 32); + len += 32; + signer.Sign (buf, len, signature); + len = Base64EncodingBufferSize (64); + char * b64 = new char[len+1]; + len = ByteStreamToBase64 (signature, 64, b64, len); + b64[len] = 0; + sig = b64; + delete[] b64; + } + else + return false; + } + } + SSL_free (ssl); + } else return false; - SSL_CTX_free (ctx); + SSL_CTX_free (ctx); return true; -} +} int main(int argc, char * argv[]) { From 87e1fdde092da0a6dadef0574c4c8dcec447752f Mon Sep 17 00:00:00 2001 From: Jeff Becker Date: Sun, 18 Feb 2018 10:14:45 -0500 Subject: [PATCH 2/9] update i2pd submodule --- i2pd | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/i2pd b/i2pd index 0b560fd..df304fb 160000 --- a/i2pd +++ b/i2pd @@ -1 +1 @@ -Subproject commit 0b560fdd27da1a6a8582a013b4d975a3c07e46d0 +Subproject commit df304fb38b07790dc42bb8f73262fa8a3b7111d0 From 706d6b56d3a2d1f1b1ee4464e280f84508e14a5d Mon Sep 17 00:00:00 2001 From: Jeff Becker Date: Sun, 18 Feb 2018 09:53:51 -0500 Subject: [PATCH 3/9] update --- vanitygen.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/vanitygen.cpp b/vanitygen.cpp index 52aa878..1a48e72 100644 --- a/vanitygen.cpp +++ b/vanitygen.cpp @@ -234,7 +234,6 @@ int main (int argc, char * argv[]) case i2p::data::SIGNING_KEY_TYPE_RSA_SHA384_3072: case i2p::data::SIGNING_KEY_TYPE_RSA_SHA512_4096: case i2p::data::SIGNING_KEY_TYPE_GOSTR3410_TC26_A_512_GOSTR3411_512: - case i2p::data::SIGNING_KEY_TYPE_GOSTR3410_TC26_A_512_GOSTR3411_512_TEST: std::cout << "Sorry, i don't can generate adress for this signature type" << std::endl; return 0; break; @@ -259,7 +258,6 @@ int main (int argc, char * argv[]) MutateByte=320; break; case i2p::data::SIGNING_KEY_TYPE_GOSTR3410_CRYPTO_PRO_A_GOSTR3411_256: - case i2p::data::SIGNING_KEY_TYPE_GOSTR3410_CRYPTO_PRO_A_GOSTR3411_256_TEST: break; } From 7ba680ef9dbbaf009b9c257122116783cae75fd5 Mon Sep 17 00:00:00 2001 From: l-n-s Date: Sun, 4 Mar 2018 03:01:54 -0500 Subject: [PATCH 4/9] update gitignore --- .gitignore | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index f31fffe..ffd5e52 100644 --- a/.gitignore +++ b/.gitignore @@ -9,10 +9,13 @@ keygen keyinfo famtool +regaddr +routerinfo +vain # private key files *.dat *.pem # certificates -*.crt \ No newline at end of file +*.crt From 8764053b51be36794ff26b44460fa5dc15fe9757 Mon Sep 17 00:00:00 2001 From: l-n-s Date: Sun, 4 Mar 2018 09:41:00 -0500 Subject: [PATCH 5/9] Add i2pdctl tool --- scripts/i2pdctl | 203 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 203 insertions(+) create mode 100755 scripts/i2pdctl diff --git a/scripts/i2pdctl b/scripts/i2pdctl new file mode 100755 index 0000000..7d926ae --- /dev/null +++ b/scripts/i2pdctl @@ -0,0 +1,203 @@ +#!/usr/bin/env python3 +import os +import json +import logging +import pprint +import argparse + +try: + import requests +except ImportError: + print("Error: requests module is required. apt install python3-requests") + exit(1) + +# Disabling annoying warnings +requests.packages.urllib3.disable_warnings( + requests.packages.urllib3.exceptions.InsecureRequestWarning) + +INFO_METHODS = { + "RouterInfo": { + "i2p.router.uptime": "", + "i2p.router.net.status": "", + "i2p.router.netdb.knownpeers": "", + "i2p.router.netdb.activepeers": "", + "i2p.router.net.bw.inbound.1s": "", + "i2p.router.net.bw.outbound.1s": "", + "i2p.router.net.tunnels.participating": "", + "i2p.router.net.tunnels.successrate": "", + "i2p.router.net.total.received.bytes": "", + "i2p.router.net.total.sent.bytes": "", + }, + "ClientServicesInfo": { + "I2PTunnel": "", + "SOCKS": "", + "HTTPProxy": "", + "SAM": "", + "BOB": "", + "I2CP": "", + } +} + +STATUS = [ + "OK", + "TESTING", + "FIREWALLED", + "HIDDEN", + "WARN_FIREWALLED_AND_FAST", + "WARN_FIREWALLED_AND_FLOODFILL", + "WARN_FIREWALLED_WITH_INBOUND_TCP", + "WARN_FIREWALLED_WITH_UDP_DISABLED", + "ERROR_I2CP", + "ERROR_CLOCK_SKEW", + "ERROR_PRIVATE_TCP_ADDRESS", + "ERROR_SYMMETRIC_NAT", + "ERROR_UDP_PORT_IN_USE", + "ERROR_NO_ACTIVE_PEERS_CHECK_CONNECTION_AND_FIREWALL", + "ERROR_UDP_DISABLED_AND_TCP_UNSET", +] + +class I2PControl(object): + """Talk to I2PControl API""" + + def __init__(self, url, password='itoopie'): + self.url = url + self.password = password + self._token = None + + @property + def token(self): + """Cached authentication token""" + if not self._token: + self._token = requests.post(self.url, + json.dumps({'id': 1, 'method': 'Authenticate', + 'params': {'API': 1, 'Password': self.password}, + 'jsonrpc': '2.0'}), + verify=False).json()["result"]["Token"] + return self._token + + def request(self, method, params): + """Execute authenticated request""" + return requests.post(self.url, + json.dumps({'id': 1, 'method': method, 'params': params, + 'jsonrpc': '2.0', 'Token': self.token}), + verify=False + ) + +class I2pdctl(object): + """i2pd control""" + + def __init__(self, ctl): + self.ctl = ctl + + def execute(self, args): + """Execute raw method""" + try: + arguments = json.loads(args.arguments) + except json.decoder.JSONDecodeError: + print("Error: arguments should be a valid JSON object") + return + + resp = self.ctl.request(args.method, arguments) + + if args.json_output: + print(resp.text) + elif "result" in resp: + pprint.pprint(resp.json()["result"]) + else: + pprint.pprint(resp.json()) + + def raw_info(self, args): + """Retrieve raw JSON reply from method(s)""" + res = {} + for m in args.method: + if m not in INFO_METHODS: + print("Invalid method {}. Supported methods are {}".format(m, + ", ".join(INFO_METHODS.keys()))) + return + else: + res[m] = self.ctl.request(m, INFO_METHODS[m]).json()['result'] + + print(json.dumps(res)) + + + def print_info(self, args): + """Print information about a node in a human readable form""" + def fancy_title(string): + print("\n### {}".format(string)) + + ri_res = self.ctl.request("RouterInfo", INFO_METHODS["RouterInfo"]).json()['result'] + try: + csi_res = self.ctl.request("ClientServicesInfo", INFO_METHODS["ClientServicesInfo"]).json()['result'] + except KeyError: + csi_res = False + + fancy_title("Router info") + print("Uptime: {}".format(ri_res["i2p.router.uptime"])) + print("Status: {}".format(STATUS[ri_res["i2p.router.net.status"]])) + print("Tunnel creation success rate: {}%".format( + ri_res["i2p.router.net.tunnels.successrate"])) + print("Received: {} ({} B/s) / Sent: {} ({} B/s)".format( + ri_res["i2p.router.net.total.received.bytes"], + ri_res["i2p.router.net.bw.inbound.1s"], + ri_res["i2p.router.net.total.sent.bytes"], + ri_res["i2p.router.net.bw.outbound.1s"])) + print("Known routers: {} / Active: {}".format( + ri_res["i2p.router.netdb.knownpeers"], + ri_res["i2p.router.netdb.activepeers"])) + + if csi_res: + fancy_title("Interfaces") + for n in ["HTTPProxy", "SOCKS", "BOB", "SAM", "I2CP"]: + print("- {}:".format(n), "ON" if csi_res[n]["enabled"] == "true" else "OFF") + + if csi_res["I2PTunnel"]["client"]: + fancy_title("Client I2P Tunnels") + for tunnel in sorted(list(csi_res["I2PTunnel"]["client"].keys())): + print("-", tunnel, csi_res["I2PTunnel"]["client"][tunnel]) + + if csi_res["I2PTunnel"]["server"]: + fancy_title("Server I2P Tunnels") + for tunnel in sorted(list(csi_res["I2PTunnel"]["server"].keys())): + t = csi_res["I2PTunnel"]["server"][tunnel] + if "port" in t: + print("-", tunnel, "{}:{}".format(t["address"], t["port"])) + else: + print("-", tunnel, t["address"]) + + +def main(): + URL = os.getenv("I2PCONTROL_URL", "https://127.0.0.1:7650/") + + ctl = I2pdctl(I2PControl(URL)) + + parser = argparse.ArgumentParser() + + subparsers = parser.add_subparsers(title="actions",help="Command to execute") + + exec_parser = subparsers.add_parser("exec", description="Execute RPC method with parameters, return results or raw JSON") + exec_parser.add_argument('method', help="RPC method name") + exec_parser.add_argument('parameters', help="Parameters as raw JSON string") + exec_parser.add_argument('-j', '--json-output', action="store_true", help="Output raw JSON reply") + exec_parser.set_defaults(func=ctl.execute) + + raw_info_parser = subparsers.add_parser("raw_info", description="Retrieve JSON info from specified *Info methods") + raw_info_parser.add_argument('method', nargs='*', + help="RPC method(s) to retreive info. Supported methods: {}".format(", ".join(INFO_METHODS.keys()))) + raw_info_parser.set_defaults(func=ctl.raw_info) + + print_info_parser = subparsers.add_parser("info", description="Print generic information about node in a human readable form") + print_info_parser.set_defaults(func=ctl.print_info) + + args = parser.parse_args() + + if hasattr(args, "func"): + try: + args.func(args) + except requests.exceptions.ConnectionError: + print("Error: I2PControl URL is unavailable. Check your i2pd settings and network connection.") + exit(1) + else: + parser.print_help() + +if __name__ == "__main__": + main() From cff429a18bd44916de42b36c3e7a3d7441d77d2a Mon Sep 17 00:00:00 2001 From: l-n-s Date: Sun, 4 Mar 2018 09:46:27 -0500 Subject: [PATCH 6/9] i2pdctl: Expose I2PControl password as environment variable --- scripts/i2pdctl | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/scripts/i2pdctl b/scripts/i2pdctl index 7d926ae..cf07f22 100755 --- a/scripts/i2pdctl +++ b/scripts/i2pdctl @@ -167,8 +167,9 @@ class I2pdctl(object): def main(): URL = os.getenv("I2PCONTROL_URL", "https://127.0.0.1:7650/") + PASSWORD = os.getenv("I2PCONTROL_PASSWORD", "itoopie") - ctl = I2pdctl(I2PControl(URL)) + ctl = I2pdctl(I2PControl(URL, PASSWORD)) parser = argparse.ArgumentParser() From bb820de2faa7b1907544901ae65e27833e65f91f Mon Sep 17 00:00:00 2001 From: l-n-s Date: Mon, 5 Mar 2018 18:44:11 +0000 Subject: [PATCH 7/9] i2pdctl: s/arguments/parameters (#43) --- scripts/i2pdctl | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/scripts/i2pdctl b/scripts/i2pdctl index cf07f22..1119a44 100755 --- a/scripts/i2pdctl +++ b/scripts/i2pdctl @@ -92,12 +92,12 @@ class I2pdctl(object): def execute(self, args): """Execute raw method""" try: - arguments = json.loads(args.arguments) + parameters = json.loads(args.parameters) except json.decoder.JSONDecodeError: - print("Error: arguments should be a valid JSON object") + print("Error: parameters should be a valid JSON object") return - resp = self.ctl.request(args.method, arguments) + resp = self.ctl.request(args.method, parameters) if args.json_output: print(resp.text) From dff8d6791d3b01da95f9b9d7a08174e9c7c6ecb6 Mon Sep 17 00:00:00 2001 From: Sammael <36346388+borned-mind@users.noreply.github.com> Date: Thu, 26 Apr 2018 23:35:07 +0700 Subject: [PATCH 8/9] Delete -mavx --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index ef14d1c..fb46dac 100644 --- a/Makefile +++ b/Makefile @@ -50,7 +50,7 @@ regaddr: $(OBJECTS) $(CXX) -o regaddr regaddr.o $(LDFLAGS) $(LIBS) vain: $(OBJECTS) - $(CXX) -o vain vanitygen.o $(LDFLAGS) -mavx $(LIBS) + $(CXX) -o vain vanitygen.o $(LDFLAGS) $(LIBS) $(OBJECTS): libi2pd.a From 9bb02b6b0ad0acb0c0c4ec0c10c715f30f470eaf Mon Sep 17 00:00:00 2001 From: l-n-s Date: Fri, 11 May 2018 13:55:25 +0000 Subject: [PATCH 9/9] Updates (#46) Human readable byte sizes and time --- scripts/i2pdctl | 26 +++++++++++++++++++++----- 1 file changed, 21 insertions(+), 5 deletions(-) diff --git a/scripts/i2pdctl b/scripts/i2pdctl index 1119a44..dd128bb 100755 --- a/scripts/i2pdctl +++ b/scripts/i2pdctl @@ -4,6 +4,7 @@ import json import logging import pprint import argparse +import datetime try: import requests @@ -56,6 +57,20 @@ STATUS = [ "ERROR_UDP_DISABLED_AND_TCP_UNSET", ] +SUFFIXES = ['B','KB','MB','GB','TB'] + +def humanize_size(size, precision=2): + """Bytes to human readable size""" + suffixIndex = 0 + while size > 1024: + suffixIndex += 1 + size = size / 1024.0 + return "{}{}".format(round(size ,precision), SUFFIXES[suffixIndex]) + +def humanize_time(milliseconds): + """Seconds to human readable time""" + return str(datetime.timedelta(milliseconds=milliseconds)) + class I2PControl(object): """Talk to I2PControl API""" @@ -132,15 +147,16 @@ class I2pdctl(object): csi_res = False fancy_title("Router info") - print("Uptime: {}".format(ri_res["i2p.router.uptime"])) + print("Uptime: {}".format( + humanize_time(int(ri_res["i2p.router.uptime"])))) print("Status: {}".format(STATUS[ri_res["i2p.router.net.status"]])) print("Tunnel creation success rate: {}%".format( ri_res["i2p.router.net.tunnels.successrate"])) print("Received: {} ({} B/s) / Sent: {} ({} B/s)".format( - ri_res["i2p.router.net.total.received.bytes"], - ri_res["i2p.router.net.bw.inbound.1s"], - ri_res["i2p.router.net.total.sent.bytes"], - ri_res["i2p.router.net.bw.outbound.1s"])) + humanize_size(int(ri_res["i2p.router.net.total.received.bytes"])), + humanize_size(int(ri_res["i2p.router.net.bw.inbound.1s"])), + humanize_size(int(ri_res["i2p.router.net.total.sent.bytes"])), + humanize_size(int(ri_res["i2p.router.net.bw.outbound.1s"])))) print("Known routers: {} / Active: {}".format( ri_res["i2p.router.netdb.knownpeers"], ri_res["i2p.router.netdb.activepeers"]))