From 9685c1adafd0e3feaf8813a68acff77176738da2 Mon Sep 17 00:00:00 2001 From: Rusty Russell Date: Fri, 15 Jul 2022 14:00:48 +0930 Subject: [PATCH] lightningd: remove getsharedsecret. This was introduced to allow creating a shared secret, but it's better to use makesecret which creates unique secrets. getsharedsecret being a generic ECDH function allows the caller to initiate conversations as if it was us; this is generally OK, since we don't allow untrusted API access, but the commando plugin had to blacklist this for read-only runes explicitly. Since @ZmnSCPxj never ended up using this after introducing it, simply remove it. Signed-off-by: Rusty Russell Changelog-Removed: JSONRPC: `getsharedsecret` API: use `makesecret` --- contrib/msggen/msggen/utils/utils.py | 1 - contrib/pyln-client/pyln/client/lightning.py | 12 --- doc/Makefile | 1 - doc/index.rst | 1 - doc/lightning-getsharedsecret.7.md | 94 -------------------- doc/schemas/getsharedsecret.schema.json | 16 ---- lightningd/hsm_control.c | 29 ------ tests/test_misc.py | 26 ------ 8 files changed, 180 deletions(-) delete mode 100644 doc/lightning-getsharedsecret.7.md delete mode 100644 doc/schemas/getsharedsecret.schema.json diff --git a/contrib/msggen/msggen/utils/utils.py b/contrib/msggen/msggen/utils/utils.py index 59586cd34..e68a1ce5e 100644 --- a/contrib/msggen/msggen/utils/utils.py +++ b/contrib/msggen/msggen/utils/utils.py @@ -93,7 +93,6 @@ def load_jsonrpc_service(schema_dir: str = None): # "funderupdate", # "getlog", "GetRoute", - # "getsharedsecret", "ListForwards", # "listoffers", "ListPays", diff --git a/contrib/pyln-client/pyln/client/lightning.py b/contrib/pyln-client/pyln/client/lightning.py index 2b1844f8e..38fc7563f 100644 --- a/contrib/pyln-client/pyln/client/lightning.py +++ b/contrib/pyln-client/pyln/client/lightning.py @@ -1442,18 +1442,6 @@ class LightningRpc(UnixDomainSocketRpc): } return self.call("checkmessage", payload) - def getsharedsecret(self, point, **kwargs): - """ - Compute the hash of the Elliptic Curve Diffie Hellman shared - secret point from this node private key and an - input {point}. - """ - payload = { - "point": point - } - payload.update({k: v for k, v in kwargs.items()}) - return self.call("getsharedsecret", payload) - def keysend(self, destination, amount_msat=None, label=None, maxfeepercent=None, retry_for=None, maxdelay=None, exemptfee=None, extratlvs=None, msatoshi=None): diff --git a/doc/Makefile b/doc/Makefile index f9375b406..3f5a39453 100644 --- a/doc/Makefile +++ b/doc/Makefile @@ -34,7 +34,6 @@ MANPAGES := doc/lightning-cli.1 \ doc/lightning-funderupdate.7 \ doc/lightning-fundpsbt.7 \ doc/lightning-getroute.7 \ - doc/lightning-getsharedsecret.7 \ doc/lightning-hsmtool.8 \ doc/lightning-invoice.7 \ doc/lightning-keysend.7 \ diff --git a/doc/index.rst b/doc/index.rst index 3d92e23ac..87e6601af 100644 --- a/doc/index.rst +++ b/doc/index.rst @@ -59,7 +59,6 @@ Core Lightning Documentation lightning-getinfo lightning-getlog lightning-getroute - lightning-getsharedsecret lightning-help lightning-hsmtool lightning-invoice diff --git a/doc/lightning-getsharedsecret.7.md b/doc/lightning-getsharedsecret.7.md deleted file mode 100644 index 505986a6e..000000000 --- a/doc/lightning-getsharedsecret.7.md +++ /dev/null @@ -1,94 +0,0 @@ -lightning-getsharedsecret -- Command for computing an ECDH -========================================================== - -SYNOPSIS --------- - -**getsharedsecret** *point* - -DESCRIPTION ------------ - -The **getsharedsecret** RPC command computes a shared secret from a -given public *point*, and the secret key of this node. -The *point* is a hexadecimal string of the compressed public -key DER-encoding of the SECP256K1 point. - -RETURN VALUE ------------- - -[comment]: # (GENERATE-FROM-SCHEMA-START) -On success, an object is returned, containing: -- **shared_secret** (hex): the SHA-2 of the compressed encoding of the shared secp256k1 point (always 64 characters) - -[comment]: # (GENERATE-FROM-SCHEMA-END) - -This command may fail if communications with the HSM has a -problem; -by default lightningd uses a software "HSM" which should -never fail in this way. -(As of the time of this writing there is no true hardware -HSM that lightningd can use, but we are leaving this -possibilty open in the future.) -In that case, it will return with an error code of 800. - -CRYPTOGRAPHIC STANDARDS ------------------------ - -This serves as a key agreement scheme in elliptic-curve based -cryptographic standards. - -However, note that most key agreement schemes based on -Elliptic-Curve Diffie-Hellman do not hash the DER-compressed -point. -Standards like SECG SEC-1 ECIES specify using the X coordinate -of the point instead. -The Lightning BOLT standard (which `lightningd` uses), unlike -most other cryptographic standards, specifies the SHA-256 hash -of the DER-compressed encoding of the point. - -It is not possible to extract the X coordinate of the ECDH point -via this API, since there is no known way to reverse the 256-bit -SHA-2 hash function. -Thus there is no way to implement ECIES and similar standards using -this API. - -If you know the secret key behind *point*, you do not need to -even call **getsharedsecret**, you can just multiply the secret key -with the node public key. - -Typically, a sender will generate an ephemeral secret key -and multiply it with the node public key, -then use the result to derive an encryption key -for a symmetric encryption scheme -to encrypt a message that can be read only by that node. -Then the ephemeral secret key is multiplied -by the standard generator point, -and the ephemeral public key and the encrypted message is -sent to the node, -which then uses **getsharedsecret** to derive the same key. - -The above sketch elides important details like -key derivation function, stream encryption scheme, -message authentication code, and so on. -You should follow an established standard and avoid -rolling your own crypto. - -AUTHOR ------- - -ZmnSCPxj <> is mainly responsible. - -SEE ALSO --------- - -RESOURCES ---------- - -* BOLT 4: -* BOLT 8: -* SECG SEC-1 ECIES: -* Main web site: - - -[comment]: # ( SHA256STAMP:47c5b466b02b80d40937f40c725733f72c20f3bc26cc7f4dacd5ef858ab0282b) diff --git a/doc/schemas/getsharedsecret.schema.json b/doc/schemas/getsharedsecret.schema.json deleted file mode 100644 index 276ea1e09..000000000 --- a/doc/schemas/getsharedsecret.schema.json +++ /dev/null @@ -1,16 +0,0 @@ -{ - "$schema": "http://json-schema.org/draft-07/schema#", - "type": "object", - "additionalProperties": true, - "required": [ - "shared_secret" - ], - "properties": { - "shared_secret": { - "type": "hex", - "description": "the SHA-2 of the compressed encoding of the shared secp256k1 point", - "maxLength": 64, - "minLength": 64 - } - } -} diff --git a/lightningd/hsm_control.c b/lightningd/hsm_control.c index c30895499..5145f9095 100644 --- a/lightningd/hsm_control.c +++ b/lightningd/hsm_control.c @@ -128,26 +128,6 @@ struct ext_key *hsm_init(struct lightningd *ld) return bip32_base; } -static struct command_result *json_getsharedsecret(struct command *cmd, - const char *buffer, - const jsmntok_t *obj UNNEEDED, - const jsmntok_t *params) -{ - struct pubkey *point; - struct secret ss; - struct json_stream *response; - - if (!param(cmd, buffer, params, - p_req("point", ¶m_pubkey, &point), - NULL)) - return command_param_failed(); - - ecdh(point, &ss); - response = json_stream_success(cmd); - json_add_secret(response, "shared_secret", &ss); - return command_success(cmd, response); -} - static struct command_result *json_makesecret(struct command *cmd, const char *buffer, const jsmntok_t *obj UNNEEDED, @@ -186,12 +166,3 @@ static const struct json_command makesecret_command = { "Get a pseudorandom secret key, using some {hex} data." }; AUTODATA(json_command, &makesecret_command); - -static const struct json_command getsharedsecret_command = { - "getsharedsecret", - "utility", /* FIXME: Or "crypto"? */ - &json_getsharedsecret, - "Compute the hash of the Elliptic Curve Diffie Hellman shared secret point from " - "this node private key and an input {point}." -}; -AUTODATA(json_command, &getsharedsecret_command); diff --git a/tests/test_misc.py b/tests/test_misc.py index cac96dcf5..77f8f061a 100644 --- a/tests/test_misc.py +++ b/tests/test_misc.py @@ -2245,32 +2245,6 @@ def test_sendcustommsg(node_factory): ]) -@pytest.mark.developer("needs --dev-force-privkey") -def test_getsharedsecret(node_factory): - """ - Test getsharedsecret command. - """ - # From BOLT 8 test vectors. - options = [ - {"dev-force-privkey": "1212121212121212121212121212121212121212121212121212121212121212"}, - {} - ] - l1, l2 = node_factory.get_nodes(2, opts=options) - - # Check BOLT 8 test vectors. - shared_secret = l1.rpc.getsharedsecret("028d7500dd4c12685d1f568b4c2b5048e8534b873319f3a8daa612b469132ec7f7")['shared_secret'] - assert (shared_secret == "1e2fb3c8fe8fb9f262f649f64d26ecf0f2c0a805a767cf02dc2d77a6ef1fdcc3") - - # Clear the forced privkey of l1. - del l1.daemon.opts["dev-force-privkey"] - l1.restart() - - # l1 and l2 can generate the same shared secret - # knowing only the public key of the other. - assert (l1.rpc.getsharedsecret(l2.info["id"])["shared_secret"] - == l2.rpc.getsharedsecret(l1.info["id"])["shared_secret"]) - - @pytest.mark.developer("needs --dev-force-privkey") def test_makesecret(node_factory): """