Add comment around the config sample - #158
gaelgatelement wants to merge 2 commits into
Conversation
| # The secret can be generated with: | ||
| # | ||
| # openssl genpkey -algorithm X25519 -outform DER \ | ||
| # | openssl asn1parse -inform DER -strparse 14 -out /dev/stdout -noout \ |
There was a problem hiding this comment.
-strparse 14 feels very fragile, I'm not a huge fan.
If the first command changes the way it serialises the field, maybe starting populating an optional field in the ASN.1 payload (if such a thing exists), it could shift the start offset of the OCTET STRING which currently sits at offset 14 basically 'by chance'
(e.g. see https://lapo.it/asn1js/#MC4CAQAwBQYDK2VuBCIEINDXpfQRUBxCOFc6C85XxB9h1SS8ab9eJrhiY4uw3w5z)
Apparently x25519 has no real 'structure' as such and you can get away with just using 32 random bytes because it'll also get clamped at use time.
Or to clamp yourself you can apparently use:
import base64
import secrets
scalar = bytearray(secrets.token_bytes(32))
scalar[0] &= 248
scalar[31] = (scalar[31] & 127) | 64
print(base64.b64encode(scalar).decode())(LLM, unvetted by me, but sounds roughly correct based on my previous exposure to x25519)
I think I'd be curious on security team's input into what is best here.
There was a problem hiding this comment.
X25519 private keys are truly just a sequence of 32 random bytes. There is no other constraint imposed on them and there is no need to do the clamping yourself.
The only exception is if we are dealing with a very low-level X25519 library which might expect an already clamped scalar. I have verified that this is not the case in this instance: matrix-content-scanner-python uses CryptoHandler, which uses vodozemac's Curve25519SecretKey::from_slice under the hood, which in turn uses x25519_dalek's StaticSecret. This expects an arbitrary 32-byte sequence as the input.
The only thing openssl genpkey -algorithm X25519 -outform DER adds on top is to encode it as a DER, which adds some extra ASN1 structure, such as packing it in a sequence of objects:
at 16:42:45 ❯ openssl genpkey -algorithm X25519 -outform DER | openssl asn1parse -inform DER
0:d=0 hl=2 l= 46 cons: SEQUENCE
2:d=1 hl=2 l= 1 prim: INTEGER :00
5:d=1 hl=2 l= 5 cons: SEQUENCE
7:d=2 hl=2 l= 3 prim: OBJECT :X25519
12:d=1 hl=2 l= 34 prim: OCTET STRING [HEX DUMP]:042090F76233CA1D2FD2C018EB3F8C8C0FDDCCDDB7621AD87A200AD9D92E5093AC70
So my recommendation would be to replace the instruction with one simply generating 32 random bytes, encoded with base64.
There was a problem hiding this comment.
If we need a snippet using the openssl utility, I think this would do the trick:
openssl rand -base64 32 > ./path/to/request_secretThere was a problem hiding this comment.
Thank you very much, I've adjusted the documentation accordingly.
I think this information needs to be near the secret configuration. At the moment it is only present in the release note : https://github.com/element-hq/matrix-content-scanner-python/releases/tag/v1.3.0
People could risk generating any random 32 bytes, thinking it would be a valid private key. But x25519 has a couple more constraints, so any random 32 bytes would not be correct.