[trashcancel?] libtoilet is intended to use the e-x fork of electrumx to be able connect to a handful of different cryptocurrencies. the electrum protocol doesn't include ssl fingerprints in peer exchange yet, which might mean a mitm can easily offer you a fake peer network. this is something that is not too complex to add and can reduce the censorship/difficulty tradeoff for cryptocurrency clients and toilet shredders both. electrumx is at https://github.com/kyuupichan/electrumx electrumx uses a quick small network library that i think of as a clean hack at https://github.com/kyuupichan/aiorpcX basically it integrates with python's standard asyncio sockets implementation, which has support for SSL. the fork of electrumx that retains support for more coins is at https://github.com/spesmilo/electrumx . --- I glanced through some electrumx code, but I'm confused as to whether it was kyuupichan's or spesmilos. But since the codebases are likely based on the same trees, hopefully I can reuse the glancing. I thought I was looking at spesmilo's code, so I was focusing on making additions to the client rather than the protocol, since I think it might be kyuupichan who specifies the protocol, really not sure of this, do not know. What seemed to make the first sense to me would be to: - add ssl fingerprints to hardcided coin peers in lib/coins.py - add parsing of the fingerprints to Peer.from_real_name() in lib/peer.py and generation of them to Peer.real_name() - add code to PeerManager._verify_peer() in server/peers.py to check ssl fingerprints, which means a little more api and source digging to implement It's notable that in the source, it describes the peer description format as "as on IRC", so the idea of finding the IRC community that distributes peer addresses, and adding fingerprinting to the tools they use, could help here.
electrumx uses a quick small network library that i think of as a clean hack at https://github.com/kyuupichan/aiorpcX
"clean" because it's not full of delusional spaghetti, not because it is particularly more elegant than other code that matches that property
I'm thinking to start implementing what I came up with glancing through, I'd first want to be able to query an aiorpcx socket for its ssl fingerprint, which likely means getting the python socket from the transport and reviewing its ssl attribute. Then I can reuse looking that stuff up to implement the verification, too.
When I get confused around how the python code connects to asyncio's socket stuff, I visit aiorpcx/rawsocket.py and check the RSClient class. This is where kyuupichan's code makes network connections and connects with asyncio. Access to the transport can be seen in RSTransport.connection_made(transport) in that same file, where the transport is queried for its peername: transport.get_extra_info('peername'). -- I'd like to look at the documentation of this. I think I find that from some keyword where the connection is initiated, maybe in the server code outside of aiorpcx. To find that I search for calls to `connect_rs` which is how aiorpcx exports its RSClient class constructor to look like a function. Popping around a bit: it's loop.create_connection . I can websearch that with some catalysing term like 'asyncio'. And it worked; here's the python documentation on this: https://docs.python.org/3/library/asyncio-eventloop.html#opening-network-con...
The docs link to different things that can be queried from SSL sockets. One of them is a peer certificate. That sounds like a helpful thing to have a fingerprint of, but I don't know SSL well so it could be the wrong thing, who knows. Anyway I'll assume it's what I need, set a breakpoint after an SSL connection is made, and see how to get the fingerprint. The transport object gets the SSL information via the get_extra_info method: https://docs.python.org/3/library/asyncio-protocol.html#asyncio.BaseTranspor...
To get access to connection information from a peer, I'll likely need some part of the peer that is associated with an actual live connection. Still recomprehending where or how that is held in the electrumx source I'm looking at (which could be kyuupichan's or spesmilo's).
-> the server.peers.PeerManager._verify_peer() method I'm thinking of adding ssl checking to takes both a 'session' object and a 'peer' object. The 'session' object is returned from asyncio, and is the live connection. The 'peer' object stores the address information and other metadata regarding the peer. So, can I get a transport from a session object? Or do I need to add something outside this function?
I'm kinda confused, my mental habits are messing with each other. I have some wrong assumptions. The session object is not an asyncio session object. It's a kyuupichan session object. It contains an attribute called 'transport'. This is also not an asyncio transport object, but rather a kyuupichan transport object.
kyuupichan session object: electrumx.server.peers.PeerSession kyuupichan transport object: aiorpcx.rawsocket.RSTransport I've already glanced at RSTransport a little, so maybe I'll start there
session.transport._asyncio_transport :) (Pdb) p session.transport._asyncio_transport.get_extra_info('peername') ('23.88.0.175', 50002) (Pdb) p session.transport._asyncio_transport.get_extra_info('peercert') {} blargh, is this not an ssl connection?
my browser froze up and came back. electrumx.lib.coins.Coin.PEER_DEFAULT_PORTS shows that 50002 is the electrum SSL port.
I'm guessing that a peer cert is just not what I am hoping it is, some other thing. (Pdb) p session.transport._asyncio_transport.get_extra_info('cipher') ('TLS_AES_256_GCM_SHA384', 'TLSv1.3', 256) (Pdb) p session.transport._asyncio_transport.get_extra_info('sslcontext') <ssl.SSLContext object at 0xffffb794c640> (Pdb) p session.transport._asyncio_transport.get_extra_info('ssl_object') <ssl.SSLObject object at 0xffffb7930c70>
so I websearched around ssl python connection fingerprint or somesuch and got to https://www.solrac.nl/retrieve-thumbprint-ssltls-python/ which has example code showing using the peercert, but they pass True to a function to get it, which seems to work: (Pdb) ctx = session.transport._asyncio_transport.get_extra_info('ssl_object') (Pdb) p ctx.getpeercert() {} (Pdb) p ctx.getpeercert(True) b'0\x82\x03\x060\x82\x01\xee\x02\t\x00\xef\xd4m\x9e8\x1b\xc4\xe60\r\x06\t*\x86H\x86\xf7\r\x01\x01\x0b\x05\x000E1\x0b0\t\x06\x03U\x04\x06\x13\x02AU1\x130\x11\x06\x03U\x04\x08\x0c\nSome-State1!0\x1f\x06\x03U\x04\n\x0c\x18Internet Widgits Pty Ltd0\x1e\x17\r190111101520Z\x17\r240110101520Z0E1\x0b0\t\x06\x03U\x04\x06\x13\x02AU1\x130\x11\x06\x03U\x04\x08\x0c\nSome-State1!0\x1f\x06\x03U\x04\n\x0c\x18Internet Widgits Pty Ltd0\x82\x01"0\r\x06\t*\x86H\x86\xf7\r\x01\x01\x01\x05\x00\x03\x82\x01\x0f\x000\x82\x01\n\x02\x82\x01\x01\x00\xb7M\xf1f\xbe\xf8HR,\xdd\x1e\x81\xbbq\xe9^\x11\xc0\xb3{_\xcf\xfa\xc9\xd3\r,\xaf\xe1:\x1d\xee\xfb\x84\x90\xb6\x10\xd9\x83\xeb\x91C\x85\xef\x17\x85\xdb\xf7>9\xa4g~\xd0.?\xe9\xdb\x1d\x07\xecXhH\xc7\xd4\xb2\xf1\r\xc3\x8d\xd1\xb6\x8cn\xb2\xe5\x06\xd0P\xadt\x8c\x97J\xe8\x10\xe2\x11x\x83\x8f8\xc3\x10*\x07m8\x05\x89\xba\x81af#y\x88h\x9e\xb5\xb6\xbf\x02D}\xea\x90\x8a\xe4\x1b\xf4\xd2a\x1b\xcd\xe6y+BO<B\x8dJ\x97\xc7\xe4\xd3\xb31\r\xe3\xf88\xb7\xb4C\xbb8\x12\xae\xd5\xfb\x1b\xad\x1ck\xab\x88\x94\x8c\xc8\x06O\x16*\x87\xa9Q\xc9iy\xc5\x95@\x16\xaadDQ\\>\xd4\x16\xfe\xa8P\xaf#\x95GP\xf0\xe7S\\w(]+\xa0\xcd\xd4\xd3PM\xf2\x10\xed\xe5\xb2\x9d\x0ePJ\x8d\x163-\xa0\x803\xef\xd7D\x19m\xa9\x96l\xb4\x88\x8c\t\xb8\xd7\x9a\xd4\xb0>\xeb\xb1\x0f\x03\xff\x1e\xb0S\xb8#\x80\n\xda\xcd\xb7\x02\x03\x01\x00\x010\r\x06\t*\x86H\x86\xf7\r\x01\x01\x0b\x05\x00\x03\x82\x01\x01\x00\x18\xc7\x9d\xf6\xbe\x12q\x101\xaa\x1a\xa1\xcf\xcfb\xdc\xde\x92\xaaAVP\xe19Y\xc0T_{\x0fM\x18\xd5\xc6\xeeI\xd4\x0b\xd0kh\xd0:\xe5\xc3\x17\x8a\x08\xb5\t\xa8U\xe3W\xee\xc8\xb9\xcb+>\x04\xa2\xe7\xbd\x7f\xa4\x9bs\xa4\xfc=Z]H%\xac\xe6\x9dx~l\xaf\xe1\xe5\xfe\x12\x12\xdb\x8aL\x14\x1f%,\xa1v\x1e\xe5S\x11R\xdfJ\xc3\xe7\x80\xce\x8c\xc1\x17\xca\x1c\xb4\xd1\xee\xf8\xca7\xb3f\x90\x1d\xa6\xaa\x19p\x7f8\xd9\xf68(\xc7L\xac\x9b\xdd\xa9\x17p\x8c\'e\xee\xd0{[\xf0\xa5f\xe3\xa9\x15hY\xc3a\x8e\xd0\xb6_\xa3\x14?\x0f0.~\xa1\x89\xdb\xa7\x96\xd9\xa9\xb3\x06g\x1d\x08\xa7\x7f\xc0\xde\x9cq\xda~\xe7\xb3\xcf\x7f\x1cx>\xfb\x8c\x9ek\xa7\x1c\xf5\x01\xfc\xce\xabR\xd4\xc7\x85M\xf90\x95,i\xa7\xce\xe6TS!\xff\xe2\xc0mT/\xa2.!\x7fT\xe4\x01)\xaf\x1d{}\xbc\xb1[\x0c\xda\x8e\xc8\x94\\\x84\x8e{\xa0\xa80\xde'
note: i thought i was looking at the ssl context, but that's actually the ssl object, not the ssl context. i think the context is process-wide, where as the object is connection-specific. real ctx appears to give access to e.g. ca cert chains.
# extract fingerprint ssl_obj = session.transport._asyncio_transport.get_extra_info('ssl_object') der_cert = ssl_obj.getpeercert(True) pem_cert = ssl.DER_cert_to_PEM_cert(der_cert) cert_print = hashlib.sha256(der_cert).hexdigest()
getpeercert(binary_form=False) method of ssl.SSLObject instance Returns a formatted version of the data in the certificate provided by the other end of the SSL channel. Return None if no certificate was provided, {} if a certificate was provided, but not validated. Looking up the avenues available for validation sounds like a useful rabbit hole. People must have been doing certificate pinning for openssl connections for a long time.
(Pdb) p cert_print 'f43a3b0fe7be10206074a8cf565671a4960f616d2b56ce4b66a6e100383b2b8a'
apologies, it can take me a lot of focus to keep my body from spasming around. i'm focusing on how this might be implemented rather than getting fingerprints for other networks, which would change how my debugging session appears to me
it's been years and nobody's implemented this! right now i have a draft 'irc format' proposal that looks like: sv.satoshi.io t s-sha256.f43a3b0fe7be10206074a8cf565671a4960f61 in the the code, a 'features' dict is used. i recall the protocol might send 'features' around, although they might be flags rather than strings. anyway the nearness to a little normativeness gives me enough reason to glance through ssl norms and see if there's a standard condensed way to list fingerprints of a cert associated with their digests
haha i accidentally downloaded a standard form from the fbi regarding certifying people's fingertip-prints.
i'm getting a little too tense to do this well. here's openssl's format: SHA256 Fingerprint=E6:5A:5D:37:22:FC:EF:EA:4B:22:92:45:BC:49:D2:29:3D:84:19:BC:C3:45:23:A1:22:A4:99:20:9D:03:E6:47 I could use an equal sign instead of a dot to make it look more normative
here's my half-implemented proposal: sv.satoshi.io s t xsha256=f43a3b0fe7be10206074a8cf565671a4960f616d2b56ce4b66a6e100383b2b8a the existing code keys into the first letter of each word, so I introduced the letter 'x' to indicate a certificate fingerprint and maybe let it be more backward compatible.
given the value of sharing these fingerprints, i'll take a pause, leave the code broken just for a bit to hopefully return, and try to enumerate more of them. this will mean roughly using some code to enumerate the hardcoded coin peers from spesmilo's coins.py
i'm resuming spamming because it helps me do things that are a little productive. i'm experiencing confusion.
the script to enumerate cert fingerprints didn't output what i wanted, the output seemed short, etc. i'll try to attach it to this post to the wrong thread.
anyway i'd like to be able to know that my client is connecting to the same cert as some time in the past i think i had drafted a way to like record that or something
sv.satoshi.io s t xsha256=f43a3b0fe7be10206074a8cf565671a4960f616d2b56ce4b66a6e100383b2b8a i think i added code for this to my local repository
the electrum protocol doesn't include ssl fingerprints in peer exchange yet, which might mean a mitm can easily offer you a fake peer network.
this is something that is not too complex to add and can reduce the censorship/difficulty tradeoff for cryptocurrency clients
Almost zero cryptocurrency networks use TLS, that's very bad (and it's called TLS for decade+ now, not SSL), they all should have used it since day one over 13 years ago. Clients should do opportunistic TLS with a TOFU cert learning db, report new keys in user log (because unless the coin network peers are doing PKI or registry no one will have way to verify changes anyway), have one mode to keep locked to TOFU certs, one mode to just accept all cert changes, another mode to accept some number ot percent of cert changes per time period. Since most certs in a p2p net will be selfsigned and not in the root path, and if not Letsencrypt policy will constantly be bumping out your pinned sig forms, and verifying sigs is not as important as catching pubkey swapouts which are the real indicators of actual privkey compromise. So use pubkey pinning, instead of cert_DER pinning, see: curl --pinnedpubkey That will cut the number of pin management interrupts to just privkey swapouts and reinitialized nodes.
thanks for your reply here. i'm pursuing adding certificate fingerprint pinning to an electrumx library. i don't see how pubkey pinning differs from that much, but am not very familiar with TLS. isn't a certificate just wrapping for a pubkey?
how pubkey pinning differs from that much
Try pinning google's, or any letsencrypt, end service full DER certs, it's a maintenance headache because they're constantly changing. Pinning google's intermediate certs (pubkey or full DER), or the LE end service pubkeys, can reduce maintenance, with same security.
isn't a certificate just wrapping for a pubkey?
A wrapping, over that and more meta fields. P2P nets might not have use for much more than what's in the TOFU paragraph. Bitcoin's and other cryptos total lack of both wire privacy and coin privacy, still through to this day, almost seems nefariously intentional. Refs... openssl x509 -text https://owasp.org/www-community/controls/Certificate_and_Public_Key_Pinning https://cheatsheetseries.owasp.org/cheatsheets/Pinning_Cheat_Sheet.html https://curl.haxx.se/libcurl/c/CURLOPT_PINNEDPUBLICKEY.html https://www.netcraft.com/internet-data-mining/ssl-survey/ https://www.ssllabs.com/ssl-pulse/ https://arstechnica.com/gadgets/2018/10/browser-vendors-unite-to-end-support... https://www.bleepingcomputer.com/news/security/ietf-approves-tls-13-as-inter... https://en.wikipedia.org/wiki/Transport_Layer_Security https://tools.ietf.org/html/rfc8446 https://github.com/OWASP/www-community/blob/master/pages/controls/Certificat... https://github.com/OWASP/CheatSheetSeries/blob/master/cheatsheets/Pinning_Ch... https://github.com/curl/curl/blob/master/docs/cmdline-opts/pinnedpubkey.d https://github.com/curl/curl/blob/deb9462ff2de8e955c67ed441f5f48619a31198d/d... https://github.com/curl/curl/blob/51fde337471c9125e7bf425e7ce0a0bf53691992/d... Recommendations for Secure Use of Transport Layer Security (TLS) https://tools.ietf.org/html/rfc7525 Pervasive Monitoring Is an Attack https://tools.ietf.org/html/rfc7258 Privacy Considerations for Internet Protocols https://tools.ietf.org/html/rfc6973 Certificate Transparency https://tools.ietf.org/html/rfc6962 Strong Security Requirements for Internet Engineering Task Force Standard Protocols https://tools.ietf.org/html/rfc3365 Guidelines for Writing RFC Text on Security Considerations https://tools.ietf.org/html/rfc3552 IETF Policy on Wiretapping https://tools.ietf.org/html/rfc2804 IAB and IESG Statement on Cryptographic Technology and the Internet https://tools.ietf.org/html/rfc1984 Privacy Requirements for IETF Protocols https://tools.ietf.org/html/draft-cooper-ietf-privacy-requirements-01 It is the consensus of the IETF that our protocols be designed to avoid privacy violations to the extent possible. Handling Pervasive Monitoring in the IETF (perpass) (WG) https://www.ietf.org/proceedings/88/perpass.html https://www.ietf.org/mailman/listinfo/perpass Opportunistic Security: Some Protection Most of the Time https://tools.ietf.org/html/rfc7435.html
On 2/20/22, grarpamp <grarpamp@gmail.com> wrote:
how pubkey pinning differs from that much
Try pinning google's, or any letsencrypt, end service full DER certs, it's a maintenance headache because they're constantly changing. Pinning google's intermediate certs (pubkey or full DER), or the LE end service pubkeys, can reduce maintenance, with same security.
I had thought cert pinning was a normal further step after use of CA certs. How long's google been rotating their certs? Do you have a link regarding this?
I had thought cert pinning was a normal further step after use of CA certs.
No, they are independent, because the CA's cannot be trusted. CA's are 3rd parties in it to make money, seamless browsing as a coproduct, not to provide e2e or endpoint security or insurance. And many CA's in global cert stores are pointless and risk of state coercion or rogue. Pinning is between you and owner of the server, period, as it should be. Non-pinned CA model is still a big MITM risk. Full DER cert pinning is fine if people believe CA's and the CA scheme, but the underlying pinning of the pubkey is what is actually securing the connection and is all that is really needed. Server owners really should be publishing signed hashes of their server certs in public on different infrastructure blockchains keybase twitter linktree etc, but they don't, so you have to ask them for hashes, which if done properly is better than believing some random CA's in a MITM environment.
How long's google been rotating their certs?
Years, but they probably still do not publish cert history so backverification is broken..
participants (2)
-
grarpamp
-
Undiscussed Horrific Abuse, One Victim of Many