Support for encrypted macaroons (#521)

* encrypted macaroons

* fix GRPC env entry

* example config entry

* add pycryptodomex to requirements

* documentation

* Added pycryptodomex to pip file

Co-authored-by: Ben Arc <ben@arc.wales>
This commit is contained in:
calle 2022-02-14 17:54:05 +01:00 committed by GitHub
parent 0367ee85a7
commit 0764f4fdf1
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
9 changed files with 235 additions and 83 deletions

View file

@ -55,11 +55,15 @@ LND_GRPC_ENDPOINT=127.0.0.1
LND_GRPC_PORT=11009 LND_GRPC_PORT=11009
LND_GRPC_CERT="/home/bob/.config/Zap/lnd/bitcoin/mainnet/wallet-1/data/chain/bitcoin/mainnet/tls.cert" LND_GRPC_CERT="/home/bob/.config/Zap/lnd/bitcoin/mainnet/wallet-1/data/chain/bitcoin/mainnet/tls.cert"
LND_GRPC_MACAROON="/home/bob/.config/Zap/lnd/bitcoin/mainnet/wallet-1/data/chain/bitcoin/mainnet/admin.macaroon or HEXSTRING" LND_GRPC_MACAROON="/home/bob/.config/Zap/lnd/bitcoin/mainnet/wallet-1/data/chain/bitcoin/mainnet/admin.macaroon or HEXSTRING"
# To use an AES-encrypted macaroon, set
# LND_GRPC_MACAROON_ENCRYPTED="eNcRyPtEdMaCaRoOn"
# LndRestWallet # LndRestWallet
LND_REST_ENDPOINT=https://127.0.0.1:8080/ LND_REST_ENDPOINT=https://127.0.0.1:8080/
LND_REST_CERT="/home/bob/.config/Zap/lnd/bitcoin/mainnet/wallet-1/data/chain/bitcoin/mainnet/tls.cert" LND_REST_CERT="/home/bob/.config/Zap/lnd/bitcoin/mainnet/wallet-1/data/chain/bitcoin/mainnet/tls.cert"
LND_REST_MACAROON="/home/bob/.config/Zap/lnd/bitcoin/mainnet/wallet-1/data/chain/bitcoin/mainnet/admin.macaroon or HEXSTRING" LND_REST_MACAROON="/home/bob/.config/Zap/lnd/bitcoin/mainnet/wallet-1/data/chain/bitcoin/mainnet/admin.macaroon or HEXSTRING"
# To use an AES-encrypted macaroon, set
# LND_REST_MACAROON_ENCRYPTED="eNcRyPtEdMaCaRoOn"
# LNPayWallet # LNPayWallet
LNPAY_API_ENDPOINT=https://api.lnpay.co/v1/ LNPAY_API_ENDPOINT=https://api.lnpay.co/v1/

View file

@ -30,6 +30,7 @@ sse-starlette = "*"
jinja2 = "3.0.1" jinja2 = "3.0.1"
pyngrok = "*" pyngrok = "*"
secp256k1 = "*" secp256k1 = "*"
pycryptodomex = "*"
[dev-packages] [dev-packages]
black = "==20.8b1" black = "==20.8b1"

164
Pipfile.lock generated
View file

@ -1,7 +1,7 @@
{ {
"_meta": { "_meta": {
"hash": { "hash": {
"sha256": "bd78144379115a1566549f5f2d7dba7a96539fb5893b3999e61bc13c6847827e" "sha256": "3e19364434fd2db3748162ccc1f3b6bddcf7a382473069d15cee6eda5e07eef1"
}, },
"pipfile-spec": 6, "pipfile-spec": 6,
"requires": { "requires": {
@ -146,11 +146,11 @@
}, },
"charset-normalizer": { "charset-normalizer": {
"hashes": [ "hashes": [
"sha256:2842d8f5e82a1f6aa437380934d5e1cd4fcf2003b06fed6940769c164a480a45", "sha256:2857e29ff0d34db842cd7ca3230549d1a697f96ee6d3fb071cfa6c7393832597",
"sha256:98398a9d69ee80548c762ba991a4728bfc3836768ed226b3945908d1a688371c" "sha256:6881edbebdb17b39b4eaaa821b438bf6eddffb4468cf344f09f89def34a8b1df"
], ],
"markers": "python_version >= '3.5'", "markers": "python_version >= '3.5'",
"version": "==2.0.11" "version": "==2.0.12"
}, },
"click": { "click": {
"hashes": [ "hashes": [
@ -201,11 +201,11 @@
}, },
"httpcore": { "httpcore": {
"hashes": [ "hashes": [
"sha256:2621ee769d0236574df51b305c5f4c69ca8f0c7b215221ad247b1ee42a9a9de1", "sha256:47d772f754359e56dd9d892d9593b6f9870a37aeb8ba51e9a88b09b3d68cfade",
"sha256:435ab519628a6e2393f67812dea3ca5c6ad23b457412cd119295d9f906d96a2b" "sha256:7503ec1c0f559066e7e39bc4003fd2ce023d01cf51793e3c173b864eb456ead1"
], ],
"markers": "python_version >= '3.6'", "markers": "python_version >= '3.6'",
"version": "==0.14.5" "version": "==0.14.7"
}, },
"httptools": { "httptools": {
"hashes": [ "hashes": [
@ -427,6 +427,39 @@
], ],
"version": "==2.21" "version": "==2.21"
}, },
"pycryptodomex": {
"hashes": [
"sha256:1ca8e1b4c62038bb2da55451385246f51f412c5f5eabd64812c01766a5989b4a",
"sha256:298c00ea41a81a491d5b244d295d18369e5aac4b61b77b2de5b249ca61cd6659",
"sha256:2aa887683eee493e015545bd69d3d21ac8d5ad582674ec98f4af84511e353e45",
"sha256:2ce76ed0081fd6ac8c74edc75b9d14eca2064173af79843c24fa62573263c1f2",
"sha256:3da13c2535b7aea94cc2a6d1b1b37746814c74b6e80790daddd55ca5c120a489",
"sha256:406ec8cfe0c098fadb18d597dc2ee6de4428d640c0ccafa453f3d9b2e58d29e2",
"sha256:4d0db8df9ffae36f416897ad184608d9d7a8c2b46c4612c6bc759b26c073f750",
"sha256:530756d2faa40af4c1f74123e1d889bd07feae45bac2fd32f259a35f7aa74151",
"sha256:77931df40bb5ce5e13f4de2bfc982b2ddc0198971fbd947776c8bb5050896eb2",
"sha256:797a36bd1f69df9e2798e33edb4bd04e5a30478efc08f9428c087f17f65a7045",
"sha256:8085bd0ad2034352eee4d4f3e2da985c2749cb7344b939f4d95ead38c2520859",
"sha256:8536bc08d130cae6dcba1ea689f2913dfd332d06113904d171f2f56da6228e89",
"sha256:a4d412eba5679ede84b41dbe48b1bed8f33131ab9db06c238a235334733acc5e",
"sha256:aebecde2adc4a6847094d3bd6a8a9538ef3438a5ea84ac1983fcb167db614461",
"sha256:b276cc4deb4a80f9dfd47a41ebb464b1fe91efd8b1b8620cf5ccf8b824b850d6",
"sha256:b5a185ae79f899b01ca49f365bdf15a45d78d9856f09b0de1a41b92afce1a07f",
"sha256:c4d8977ccda886d88dc3ca789de2f1adc714df912ff3934b3d0a3f3d777deafb",
"sha256:c5dd3ffa663c982d7f1be9eb494a8924f6d40e2e2f7d1d27384cfab1b2ac0662",
"sha256:ca88f2f7020002638276439a01ffbb0355634907d1aa5ca91f3dc0c2e44e8f3b",
"sha256:d2cce1c82a7845d7e2e8a0956c6b7ed3f1661c9acf18eb120fc71e098ab5c6fe",
"sha256:d709572d64825d8d59ea112e11cc7faf6007f294e9951324b7574af4251e4de8",
"sha256:da8db8374295fb532b4b0c467e66800ef17d100e4d5faa2bbbd6df35502da125",
"sha256:e36c7e3b5382cd5669cf199c4a04a0279a43b2a3bdd77627e9b89778ac9ec08c",
"sha256:e95a4a6c54d27a84a4624d2af8bb9ee178111604653194ca6880c98dcad92f48",
"sha256:ee835def05622e0c8b1435a906491760a43d0c462f065ec9143ec4b8d79f8bff",
"sha256:f75009715dcf4a3d680c2338ab19dac5498f8121173a929872950f4fb3a48fbf",
"sha256:f8524b8bc89470cec7ac51734907818d3620fb1637f8f8b542d650ebec42a126"
],
"index": "pypi",
"version": "==3.14.1"
},
"pydantic": { "pydantic": {
"hashes": [ "hashes": [
"sha256:085ca1de245782e9b46cefcf99deecc67d418737a1fd3f6a4f511344b613a5b3", "sha256:085ca1de245782e9b46cefcf99deecc67d418737a1fd3f6a4f511344b613a5b3",
@ -684,22 +717,22 @@
}, },
"typing-extensions": { "typing-extensions": {
"hashes": [ "hashes": [
"sha256:4ca091dea149f945ec56afb48dae714f21e8692ef22a395223bcd328961b6a0e", "sha256:1a9462dcc3347a79b1f1c0271fbe79e844580bb598bafa1ed208b94da3cdcd42",
"sha256:7f001e5ac290a0c0401508864c7ec868be4e701886d5b573a9528ed3973d9d3b" "sha256:21c85e0fe4b9a155d0799430b0ad741cdce7e359660ccbd8b530613e8df88ce2"
], ],
"index": "pypi", "index": "pypi",
"version": "==4.0.1" "version": "==4.1.1"
}, },
"uvicorn": { "uvicorn": {
"extras": [ "extras": [
"standard" "standard"
], ],
"hashes": [ "hashes": [
"sha256:8b16d9ecb76500f7804184f182835fe8a2b54716d3b0b6bb2da0b2b192f62c73", "sha256:25850bbc86195a71a6477b3e4b3b7b4c861fb687fb96912972ce5324472b1011",
"sha256:dffbacb8cc25d924d68d231d2c478c4fe6727c36537d8de21e5de591b37afc41" "sha256:e85872d84fb651cccc4c5d2a71cf7ead055b8fb4d8f1e78e36092282c0cf2aec"
], ],
"index": "pypi", "index": "pypi",
"version": "==0.17.1" "version": "==0.17.4"
}, },
"uvloop": { "uvloop": {
"hashes": [ "hashes": [
@ -819,53 +852,50 @@
"toml" "toml"
], ],
"hashes": [ "hashes": [
"sha256:012157499ec4f135fc36cd2177e3d1a1840af9b236cbe80e9a5ccfc83d912a69", "sha256:1245ab82e8554fa88c4b2ab1e098ae051faac5af829efdcf2ce6b34dccd5567c",
"sha256:0a34d313105cdd0d3644c56df2d743fe467270d6ab93b5d4a347eb9fec8924d6", "sha256:1bc6d709939ff262fd1432f03f080c5042dc6508b6e0d3d20e61dd045456a1a0",
"sha256:11e61c5548ecf74ea1f8b059730b049871f0e32b74f88bd0d670c20c819ad749", "sha256:25e73d4c81efa8ea3785274a2f7f3bfbbeccb6fcba2a0bdd3be9223371c37554",
"sha256:152cc2624381df4e4e604e21bd8e95eb8059535f7b768c1fb8b8ae0b26f47ab0", "sha256:276b13cc085474e482566c477c25ed66a097b44c6e77132f3304ac0b039f83eb",
"sha256:1b4285fde5286b946835a1a53bba3ad41ef74285ba9e8013e14b5ea93deaeafc", "sha256:2aed4761809640f02e44e16b8b32c1a5dee5e80ea30a0ff0912158bde9c501f2",
"sha256:27a94db5dc098c25048b0aca155f5fac674f2cf1b1736c5272ba28ead2fc267e", "sha256:2dd70a167843b4b4b2630c0c56f1b586fe965b4f8ac5da05b6690344fd065c6b",
"sha256:27ac7cb84538e278e07569ceaaa6f807a029dc194b1c819a9820b9bb5dbf63ab", "sha256:352c68e233409c31048a3725c446a9e48bbff36e39db92774d4f2380d630d8f8",
"sha256:2a491e159294d756e7fc8462f98175e2d2225e4dbe062cca7d3e0d5a75ba6260", "sha256:3f2b05757c92ad96b33dbf8e8ec8d4ccb9af6ae3c9e9bd141c7cc44d20c6bcba",
"sha256:2bc85664b06ba42d14bb74d6ddf19d8bfc520cb660561d2d9ce5786ae72f71b5", "sha256:448d7bde7ceb6c69e08474c2ddbc5b4cd13c9e4aa4a717467f716b5fc938a734",
"sha256:32168001f33025fd756884d56d01adebb34e6c8c0b3395ca8584cdcee9c7c9d2", "sha256:463e52616ea687fd323888e86bf25e864a3cc6335a043fad6bbb037dbf49bbe2",
"sha256:3c4ce3b647bd1792d4394f5690d9df6dc035b00bcdbc5595099c01282a59ae01", "sha256:482fb42eea6164894ff82abbcf33d526362de5d1a7ed25af7ecbdddd28fc124f",
"sha256:433b99f7b0613bdcdc0b00cc3d39ed6d756797e3b078d2c43f8a38288520aec6", "sha256:56c4a409381ddd7bbff134e9756077860d4e8a583d310a6f38a2315b9ce301d0",
"sha256:4578728c36de2801c1deb1c6b760d31883e62e33f33c7ba8f982e609dc95167d", "sha256:56d296cbc8254a7dffdd7bcc2eb70be5a233aae7c01856d2d936f5ac4e8ac1f1",
"sha256:509c68c3e2015022aeda03b003dd68fa19987cdcf64e9d4edc98db41cfc45d30", "sha256:5e15d424b8153756b7c903bde6d4610be0c3daca3986173c18dd5c1a1625e4cd",
"sha256:51372e24b1f7143ee2df6b45cff6a721f3abe93b1e506196f3ffa4155c2497f7", "sha256:618eeba986cea7f621d8607ee378ecc8c2504b98b3fdc4952b30fe3578304687",
"sha256:5d008e0f67ac800b0ca04d7914b8501312c8c6c00ad8c7ba17754609fae1231a", "sha256:61d47a897c1e91f33f177c21de897267b38fbb45f2cd8e22a710bcef1df09ac1",
"sha256:649df3641eb351cdfd0d5533c92fc9df507b6b2bf48a7ef8c71ab63cbc7b5c3c", "sha256:621f6ea7260ea2ffdaec64fe5cb521669984f567b66f62f81445221d4754df4c",
"sha256:6e78b1e25e5c5695dea012be473e442f7094d066925604be20b30713dbd47f89", "sha256:6a5cdc3adb4f8bb8d8f5e64c2e9e282bc12980ef055ec6da59db562ee9bdfefa",
"sha256:72d9d186508325a456475dd05b1756f9a204c7086b07fffb227ef8cee03b1dc2", "sha256:6c3f6158b02ac403868eea390930ae64e9a9a2a5bbfafefbb920d29258d9f2f8",
"sha256:7d82c610a2e10372e128023c5baf9ce3d270f3029fe7274ff5bc2897c68f1318", "sha256:704f89b87c4f4737da2860695a18c852b78ec7279b24eedacab10b29067d3a38",
"sha256:7ee317486593193e066fc5e98ac0ce712178c21529a85c07b7cb978171f25d53", "sha256:72128176fea72012063200b7b395ed8a57849282b207321124d7ff14e26988e8",
"sha256:7eed8459a2b81848cafb3280b39d7d49950d5f98e403677941c752e7e7ee47cb", "sha256:78fbb2be068a13a5d99dce9e1e7d168db880870f7bc73f876152130575bd6167",
"sha256:823f9325283dc9565ba0aa2d240471a93ca8999861779b2b6c7aded45b58ee0f", "sha256:7bff3a98f63b47464480de1b5bdd80c8fade0ba2832c9381253c9b74c4153c27",
"sha256:85c5fc9029043cf8b07f73fbb0a7ab6d3b717510c3b5642b77058ea55d7cacde", "sha256:84f2436d6742c01136dd940ee158bfc7cf5ced3da7e4c949662b8703b5cd8145",
"sha256:86c91c511853dfda81c2cf2360502cb72783f4b7cebabef27869f00cbe1db07d", "sha256:9976fb0a5709988778ac9bc44f3d50fccd989987876dfd7716dee28beed0a9fa",
"sha256:8e0c3525b1a182c8ffc9bca7e56b521e0c2b8b3e82f033c8e16d6d721f1b54d6", "sha256:9ad0a117b8dc2061ce9461ea4c1b4799e55edceb236522c5b8f958ce9ed8fa9a",
"sha256:987a84ff98a309994ca77ed3cc4b92424f824278e48e4bf7d1bb79a63cfe2099", "sha256:9e3dd806f34de38d4c01416344e98eab2437ac450b3ae39c62a0ede2f8b5e4ed",
"sha256:9ed3244b415725f08ca3bdf02ed681089fd95e9465099a21c8e2d9c5d6ca2606", "sha256:9eb494070aa060ceba6e4bbf44c1bc5fa97bfb883a0d9b0c9049415f9e944793",
"sha256:a189036c50dcd56100746139a459f0d27540fef95b09aba03e786540b8feaa5f", "sha256:9fde6b90889522c220dd56a670102ceef24955d994ff7af2cb786b4ba8fe11e4",
"sha256:a4748349734110fd32d46ff8897b561e6300d8989a494ad5a0a2e4f0ca974fc7", "sha256:9fff3ff052922cb99f9e52f63f985d4f7a54f6b94287463bc66b7cdf3eb41217",
"sha256:a5d79c9af3f410a2b5acad91258b4ae179ee9c83897eb9de69151b179b0227f5", "sha256:a06c358f4aed05fa1099c39decc8022261bb07dfadc127c08cfbd1391b09689e",
"sha256:a7596aa2f2b8fa5604129cfc9a27ad9beec0a96f18078cb424d029fdd707468d", "sha256:a4f923b9ab265136e57cc14794a15b9dcea07a9c578609cd5dbbfff28a0d15e6",
"sha256:ab4fc4b866b279740e0d917402f0e9a08683e002f43fa408e9655818ed392196", "sha256:c5b81fb37db76ebea79aa963b76d96ff854e7662921ce742293463635a87a78d",
"sha256:bde4aeabc0d1b2e52c4036c54440b1ad05beeca8113f47aceb4998bb7471e2c2", "sha256:d5ed164af5c9078596cfc40b078c3b337911190d3faeac830c3f1274f26b8320",
"sha256:c72bb4679283c6737f452eeb9b2a0e570acaef2197ad255fb20162adc80bea76", "sha256:d651fde74a4d3122e5562705824507e2f5b2d3d57557f1916c4b27635f8fbe3f",
"sha256:c8582e9280f8d0f38114fe95a92ae8d0790b56b099d728cc4f8a2e14b1c4a18c", "sha256:de73fca6fb403dd72d4da517cfc49fcf791f74eee697d3219f6be29adf5af6ce",
"sha256:ca29c352389ea27a24c79acd117abdd8a865c6eb01576b6f0990cd9a4e9c9f48", "sha256:e647a0be741edbb529a72644e999acb09f2ad60465f80757da183528941ff975",
"sha256:ce443a3e6df90d692c38762f108fc4c88314bf477689f04de76b3f252e7a351c", "sha256:e92c7a5f7d62edff50f60a045dc9542bf939758c95b2fcd686175dd10ce0ed10",
"sha256:d1675db48490e5fa0b300f6329ecb8a9a37c29b9ab64fa9c964d34111788ca2d", "sha256:eeffd96882d8c06d31b65dddcf51db7c612547babc1c4c5db6a011abe9798525",
"sha256:da1a428bdbe71f9a8c270c7baab29e9552ac9d0e0cba5e7e9a4c9ee6465d258d", "sha256:f5a4551dfd09c3bd12fca8144d47fe7745275adf3229b7223c2f9e29a975ebda",
"sha256:e4ff163602c5c77e7bb4ea81ba5d3b793b4419f8acd296aae149370902cf4e92", "sha256:fac0bcc5b7e8169bffa87f0dcc24435446d329cbc2b5486d155c2e0f3b493ae1"
"sha256:e67ccd53da5958ea1ec833a160b96357f90859c220a00150de011b787c27b98d",
"sha256:e8071e7d9ba9f457fc674afc3de054450be2c9b195c470147fbbc082468d8ff7",
"sha256:fff16a30fdf57b214778eff86391301c4509e327a65b877862f7c929f10a4253"
], ],
"markers": "python_version >= '3.7'", "markers": "python_version >= '3.7'",
"version": "==6.3" "version": "==6.3.1"
}, },
"iniconfig": { "iniconfig": {
"hashes": [ "hashes": [
@ -948,11 +978,11 @@
}, },
"pytest": { "pytest": {
"hashes": [ "hashes": [
"sha256:131b36680866a76e6781d13f101efb86cf674ebb9762eb70d3082b6f29889e89", "sha256:9ce3ff477af913ecf6321fe337b93a2c0dcf2a0a1439c43f5452112c1e4280db",
"sha256:7310f8d27bc79ced999e760ca304d69f6ba6c6649c0b60fb0e04a4a77cacc134" "sha256:e30905a0c131d3d94b89624a1cc5afec3e0ba2fbdb151867d8e0ebd49850f171"
], ],
"index": "pypi", "index": "pypi",
"version": "==6.2.5" "version": "==7.0.1"
}, },
"pytest-cov": { "pytest-cov": {
"hashes": [ "hashes": [
@ -1051,10 +1081,10 @@
}, },
"tomli": { "tomli": {
"hashes": [ "hashes": [
"sha256:b5bde28da1fed24b9bd1d4d2b8cba62300bfb4ec9a6187a957e8ddb9434c5224", "sha256:939de3e7a6161af0c887ef91b7d41a53e7c5a1ca976325f429cb46ea9bc30ecc",
"sha256:c292c34f58502a1eb2bbb9f5bbc9a5ebc37bee10ffb8c2d6bbdfa8eb13cc14e1" "sha256:de526c12914f0c550d15924c62d72abc48d6fe7364aa87328337a31007fe8a4f"
], ],
"version": "==2.0.0" "version": "==2.0.1"
}, },
"typed-ast": { "typed-ast": {
"hashes": [ "hashes": [
@ -1088,11 +1118,11 @@
}, },
"typing-extensions": { "typing-extensions": {
"hashes": [ "hashes": [
"sha256:4ca091dea149f945ec56afb48dae714f21e8692ef22a395223bcd328961b6a0e", "sha256:1a9462dcc3347a79b1f1c0271fbe79e844580bb598bafa1ed208b94da3cdcd42",
"sha256:7f001e5ac290a0c0401508864c7ec868be4e701886d5b573a9528ed3973d9d3b" "sha256:21c85e0fe4b9a155d0799430b0ad741cdce7e359660ccbd8b530613e8df88ce2"
], ],
"index": "pypi", "index": "pypi",
"version": "==4.0.1" "version": "==4.1.1"
} }
} }
} }

View file

@ -36,16 +36,24 @@ Using this wallet requires the installation of the `grpcio` and `protobuf` Pytho
- `LND_GRPC_ENDPOINT`: ip_address - `LND_GRPC_ENDPOINT`: ip_address
- `LND_GRPC_PORT`: port - `LND_GRPC_PORT`: port
- `LND_GRPC_CERT`: /file/path/tls.cert - `LND_GRPC_CERT`: /file/path/tls.cert
- `LND_GRPC_MACAROON`: /file/path/admin.macaroon - `LND_GRPC_MACAROON`: /file/path/admin.macaroon or Bech64/Hex
You can also use an AES-encrypted macaroon (more info) instead by using
- `LND_GRPC_MACAROON_ENCRYPTED`: eNcRyPtEdMaCaRoOn
To encrypt your macaroon, run `./venv/bin/python lnbits/wallets/macaroon/macaroon.py`.
### LND (REST) ### LND (REST)
- `LNBITS_BACKEND_WALLET_CLASS`: **LndRestWallet** - `LNBITS_BACKEND_WALLET_CLASS`: **LndRestWallet**
- `LND_REST_ENDPOINT`: ip_address - `LND_REST_ENDPOINT`: ip_address
- `LND_REST_CERT`: /file/path/tls.cert - `LND_REST_CERT`: /file/path/tls.cert
- `LND_GRPC_MACAROON`: /file/path/admin.macaroon - `LND_REST_MACAROON`: /file/path/admin.macaroon or Bech64/Hex
or
- `LND_REST_MACAROON_ENCRYPTED`: eNcRyPtEdMaCaRoOn
### LNbits ### LNbits

View file

@ -11,6 +11,7 @@ import base64
import hashlib import hashlib
from os import environ, error, getenv from os import environ, error, getenv
from typing import Optional, Dict, AsyncGenerator from typing import Optional, Dict, AsyncGenerator
from .macaroon import load_macaroon, AESCipher
if imports_ok: if imports_ok:
import lnbits.wallets.lnd_grpc_files.lightning_pb2 as ln import lnbits.wallets.lnd_grpc_files.lightning_pb2 as ln
@ -58,12 +59,6 @@ def get_ssl_context(cert_path: str):
return context return context
def load_macaroon(macaroon_path: str):
with open(macaroon_path, "rb") as f:
macaroon_bytes = f.read()
return macaroon_bytes.hex()
def parse_checking_id(checking_id: str) -> bytes: def parse_checking_id(checking_id: str) -> bytes:
return base64.b64decode(checking_id.replace("_", "/")) return base64.b64decode(checking_id.replace("_", "/"))
@ -90,7 +85,7 @@ class LndWallet(Wallet):
self.port = int(getenv("LND_GRPC_PORT")) self.port = int(getenv("LND_GRPC_PORT"))
self.cert_path = getenv("LND_GRPC_CERT") or getenv("LND_CERT") self.cert_path = getenv("LND_GRPC_CERT") or getenv("LND_CERT")
macaroon_path = ( macaroon = (
getenv("LND_GRPC_MACAROON") getenv("LND_GRPC_MACAROON")
or getenv("LND_GRPC_ADMIN_MACAROON") or getenv("LND_GRPC_ADMIN_MACAROON")
or getenv("LND_ADMIN_MACAROON") or getenv("LND_ADMIN_MACAROON")
@ -98,10 +93,11 @@ class LndWallet(Wallet):
or getenv("LND_INVOICE_MACAROON") or getenv("LND_INVOICE_MACAROON")
) )
if macaroon_path.split(".")[-1] == "macaroon":
self.macaroon = load_macaroon(macaroon_path) encrypted_macaroon = getenv("LND_GRPC_MACAROON_ENCRYPTED")
else: if encrypted_macaroon:
self.macaroon = macaroon_path macaroon = AESCipher(description="macaroon decryption").decrypt(encrypted_macaroon)
self.macaroon = load_macaroon(macaroon)
cert = open(self.cert_path, "rb").read() cert = open(self.cert_path, "rb").read()
creds = grpc.ssl_channel_credentials(cert) creds = grpc.ssl_channel_credentials(cert)

View file

@ -1,4 +1,5 @@
import asyncio import asyncio
from pydoc import describe
import httpx import httpx
import json import json
import base64 import base64
@ -6,6 +7,7 @@ from os import getenv
from typing import Optional, Dict, AsyncGenerator from typing import Optional, Dict, AsyncGenerator
from lnbits import bolt11 as lnbits_bolt11 from lnbits import bolt11 as lnbits_bolt11
from .macaroon import load_macaroon, AESCipher
from .base import ( from .base import (
StatusResponse, StatusResponse,
@ -34,7 +36,13 @@ class LndRestWallet(Wallet):
or getenv("LND_INVOICE_MACAROON") or getenv("LND_INVOICE_MACAROON")
or getenv("LND_REST_INVOICE_MACAROON") or getenv("LND_REST_INVOICE_MACAROON")
) )
self.auth = {"Grpc-Metadata-macaroon": macaroon}
encrypted_macaroon = getenv("LND_REST_MACAROON_ENCRYPTED")
if encrypted_macaroon:
macaroon = AESCipher(description="macaroon decryption").decrypt(encrypted_macaroon)
self.macaroon = load_macaroon(macaroon)
self.auth = {"Grpc-Metadata-macaroon": self.macaroon}
self.cert = getenv("LND_REST_CERT") self.cert = getenv("LND_REST_CERT")
async def status(self) -> StatusResponse: async def status(self) -> StatusResponse:

View file

@ -0,0 +1 @@
from .macaroon import load_macaroon, AESCipher

View file

@ -0,0 +1,103 @@
from Cryptodome import Random
from Cryptodome.Cipher import AES
import base64
from hashlib import md5
import getpass
BLOCK_SIZE = 16
import getpass
def load_macaroon(macaroon: str) -> str:
"""Returns hex version of a macaroon encoded in base64 or the file path.
:param macaroon: Macaroon encoded in base64 or file path.
:type macaroon: str
:return: Hex version of macaroon.
:rtype: str
"""
# if the macaroon is a file path, load it
if macaroon.split(".")[-1] == "macaroon":
with open(macaroon, "rb") as f:
macaroon_bytes = f.read()
return macaroon_bytes.hex()
else:
# convert the bas64 macaroon to hex
try:
macaroon = base64.b64decode(macaroon).hex()
except:
pass
return macaroon
class AESCipher(object):
"""This class is compatible with crypto-js/aes.js
Encrypt and decrypt in Javascript using:
import AES from "crypto-js/aes.js";
import Utf8 from "crypto-js/enc-utf8.js";
AES.encrypt(decrypted, password).toString()
AES.decrypt(encrypted, password).toString(Utf8);
"""
def __init__(self, key=None, description=""):
self.key = key
self.description = description + " "
def pad(self, data):
length = BLOCK_SIZE - (len(data) % BLOCK_SIZE)
return data + (chr(length) * length).encode()
def unpad(self, data):
return data[: -(data[-1] if type(data[-1]) == int else ord(data[-1]))]
@property
def passphrase(self):
passphrase = self.key if self.key is not None else None
if passphrase is None:
passphrase = getpass.getpass(f"Enter {self.description}password:")
return passphrase
def bytes_to_key(self, data, salt, output=48):
# extended from https://gist.github.com/gsakkis/4546068
assert len(salt) == 8, len(salt)
data += salt
key = md5(data).digest()
final_key = key
while len(final_key) < output:
key = md5(key + data).digest()
final_key += key
return final_key[:output]
def decrypt(self, encrypted: str) -> str:
"""Decrypts a string using AES-256-CBC.
"""
passphrase = self.passphrase
encrypted = base64.b64decode(encrypted)
assert encrypted[0:8] == b"Salted__"
salt = encrypted[8:16]
key_iv = self.bytes_to_key(passphrase.encode(), salt, 32 + 16)
key = key_iv[:32]
iv = key_iv[32:]
aes = AES.new(key, AES.MODE_CBC, iv)
try:
return self.unpad(aes.decrypt(encrypted[16:])).decode()
except UnicodeDecodeError:
raise ValueError("Wrong passphrase")
def encrypt(self, message: bytes) -> str:
passphrase = self.passphrase
salt = Random.new().read(8)
key_iv = self.bytes_to_key(passphrase.encode(), salt, 32 + 16)
key = key_iv[:32]
iv = key_iv[32:]
aes = AES.new(key, AES.MODE_CBC, iv)
return base64.b64encode(b"Salted__" + salt + aes.encrypt(self.pad(message))).decode()
# if this file is executed directly, ask for a macaroon and encrypt it
if __name__ == "__main__":
macaroon = input("Enter macaroon: ")
macaroon = load_macaroon(macaroon)
macaroon = AESCipher(description="encryption").encrypt(macaroon.encode())
print("Encrypted macaroon:")
print(macaroon)

View file

@ -25,6 +25,7 @@ markupsafe==2.0.1
marshmallow==3.13.0 marshmallow==3.13.0
outcome==1.1.0 outcome==1.1.0
psycopg2-binary==2.9.1 psycopg2-binary==2.9.1
pycryptodomex==3.14.1
pydantic==1.8.2 pydantic==1.8.2
pypng==0.0.21 pypng==0.0.21
pyqrcode==1.2.1 pyqrcode==1.2.1