Skip to content

Add comment around the config sample - #158

Open
gaelgatelement wants to merge 2 commits into
mainfrom
gaelg/request-secret-path
Open

gaelgatelement wants to merge 2 commits into
mainfrom
gaelg/request-secret-path

Conversation

@gaelgatelement

Copy link
Copy Markdown
Member

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.

@gaelgatelement
gaelgatelement requested a review from a team as a code owner August 25, 2026 12:38
Comment thread config.sample.yaml Outdated
# The secret can be generated with:
#
# openssl genpkey -algorithm X25519 -outform DER \
# | openssl asn1parse -inform DER -strparse 14 -out /dev/stdout -noout \

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

-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.

@dkasak dkasak Sep 3, 2026

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If we need a snippet using the openssl utility, I think this would do the trick:

openssl rand -base64 32 > ./path/to/request_secret

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you very much, I've adjusted the documentation accordingly.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants