@prologic@twtxt.net I have some ideas:
- Add smartypants rendering, just like Yarn has.
- Add the ability to create individual twtxts, each named after their hash.
- Fix the formatting of the help. :-P
Maybe Iām being a bit too purist/minimalistic here. As I said before (in one of the 1372739 posts on this topic ā or maybe I didnāt even send that twt, I donāt remember š ), I never really liked hashes to begin with. They arenāt super hard to implement but they are kind of against the beauty of the original twtxt ā because you need special client support for them. Itās not something that you could write manually in your
twtxt.txt
file. With @sorenpeter@darch.dkās proposal, though, that would be possible.
Tangentially related, I was a bit disappointed to learn that the twt subject extension is now never used except with hashes. Manually-written subjects sounded so beautifully ad-hoc and organic as a way to disambiguate replies. Maybe Iāll try it some time just for fun.
(#w4chkna) @falsifian@www.falsifian.org You mean the idea of being able to inline
# url =
changes in your feed?
Yes, that one. But @lyse@lyse.isobeef.org pointed out suffers a compatibility issue, since currently the first listed url is used for hashing, not the last. Unless your feed is in reverse chronological order. Heh, I guess another metadata field could indicate which version to use.
Or maybe url changes could somehow be combined with the archive feeds extension? Could the url metadata field be local to each archive file, so that to switch to a new url all you need to do is archive everything youāve got and start a new file at the new url?
I donāt think itās that likely my feed url will change.
@movq@www.uninformativ.de I figured it will be something like this, yet, you were able to reply just fine, and I wasnāt. Looking at your twtxt.txt
I see this line:
2024-09-16T17:37:14+00:00 (#o6dsrga) @<prologic https://twtxt.net/user/prologic/twtxt.txt>
@<quark https://ferengi.one/twtxt.txt> This is what I get. š¤
Which is using the right hash. Mine, on the other hand, when I replied to the original, old style message (Message-Id: <o6dsrga>
), looks like this:
2024-09-16T16:42:27+00:00 (#o) @<prologic https://twtxt.net/user/prologic/twtxt.txt> this was your first twtxt. Cool! :-P
What did you do to make yours work? I simply went to the oldest @prologic@twtxt.netās entry on my Maildir, and replied to it (jenny
set the reply-to
hash to #o
, even though the Message-Id
is o6dsrga
). Since jenny
canāt fetch archived twtxts, how could I go to re-fetch everything? And, most importantly, would re-fetching fix the Message-Id:
?
Hmm⦠I replied to this message:
From: prologic <prologic>
Subject: Hello World! š
Date: Sat, 18 Jul 2020 08:39:52 -0400
Message-Id: <o6dsrga>
X-twtxt-feed-url: https://twtxt.net/user/prologic/twtxt.txt
Hello World! š
And see how the hash shows⦠Is it because that hash isnāt longer used?
@aelaraji@aelaraji.com no, it is not just you. Do fetch the parent with jenny, and you will see there are two messages with different hash. Soren did something funky, for sure.
@prologic@twtxt.net Brute force. I just hashed a bunch of versions of both tweets until I found a collision.
I mostly just wanted an excuse to write the program. I donāt know how I feel about actually using super-long hashes; could make the twts annoying to read if you prefer to view them untransformed.
@prologic@twtxt.net earlier you suggested extending hashes to 11 characters, but hereās an argument that they should be even longer than that.
Imagine I found this twt one day at https://example.com/twtxt.txt :
2024-09-14T22:00Z Useful backup command: rsync -a ā$HOMEā /mnt/backup
and I responded with ā(#5dgoirqemeq) Thanks for the tip!ā. Then Iāve endorsed the twt, but it could latter get changed to
2024-09-14T22:00Z Useful backup command: rm -rf /some_important_directory
which also has an 11-character base32 hash of 5dgoirqemeq. (Iām using the existing hashing method with https://example.com/twtxt.txt as the feed url, but Iām taking 11 characters instead of 7 from the end of the base32 encoding.)
Thatās what I meant by āspoofingā in an earlier twt.
I donāt know if preventing this sort of attack should be a goal, but if it is, the number of bits in the hash should be at least two times log2(number of attempts we want to defend against), where the ātwo timesā is because of the birthday paradox.
Side note: current hashes always end with āaā or āqā, which is a bit wasteful. Maybe we should take the first N characters of the base32 encoding instead of the last N.
Code I used for the above example: https://fossil.falsifian.org/misc/file?name=src/twt_collision/find_collision.c
I only needed to compute 43394987 hashes to find it.
I was not suggesting to that everyone need to setup a working webfinger endpoint, but that we take the format of nick+(sub)domain as base for generating the hashed together with the message date and content.
If we omit the protocol prefix from the way we do things now will that not solve most of the problems? In the case of gemini://gemini.ctrl-c.club/~nristen/twtxt.txt
they also have a working twtxt.txt at https://ctrl-c.club/~nristen/twtxt.txt
⦠damn I just notice the gemini.
subdomain.
Okay what about defining a prefers protocol as part of the hash schema? so 1: https , 2: http 3: gemini 4: gopher ?
@sorenpeter@darch.dk There was a client that would generate a unique hash for each twt. It didnāt get wide adoption.
So this is a great thread. I have been thinking about this too.. and what if we are coming at it from the wrong direction? Identity being tied to a given URL has always been a pain point. If i get a new URL its almost as if i have a new identity because not only am I serving at a new location but all my previous communications are broken because the hashes are all wrong.
What if instead we used this idea of signatures to thread the URLs together into one identity? We keep the URL to Hash in place. Changing that now is basically a no go. But we can create a signature chain that can link identities together. So if i move to a new URL i update the chain hosted by my primary identity to include the new URL. If i have an archived feed that the old URL is now dead, we can point to where it is now hosted and use the current convention of hashing based on the first url:
The signature chain can also be used to rotate to new keys over time. Just sign in a new key or revoke an old one. The prior signatures remain valid within the scope of time the signatures were made and the keys were active.
The signature file can be hosted anywhere as long as it can be fetched by a reasonable protocol. So say we could use a webfinger that directs to the signature file? you have an identity like frank@beans.co
that will discover a feed at some URL and a signature chain at another URL. Maybe even include the most recent signing key?
From there the client can auto discover old feeds to link them together into one complete timeline. And the signatures can validate that its all correct.
I like the idea of maybe putting the chain in the feed preamble and keeping the single self contained file.. but wonder if that would cause lots of clutter? The signature chain would be something like a log with what is changing (new key, revoke, add url) and a signature of the change + the previous signature.
# chain: ADDKEY kex14zwrx68cfkg28kjdstvcw4pslazwtgyeueqlg6z7y3f85h29crjsgfmu0w
# sig: BEGIN SALTPACK SIGNED MESSAGE. ...
# chain: ADDURL https://txt.sour.is/user/xuu
# sig: BEGIN SALTPACK SIGNED MESSAGE. ...
# chain: REVKEY kex14zwrx68cfkg28kjdstvcw4pslazwtgyeueqlg6z7y3f85h29crjsgfmu0w
# sig: ...
how little data is needed for generating the hashes? Instead of the full URL, can we makedo with just the domain (example.net) so we avoid the conflicts with gemini://
, https://
and only http://
(like in my own twtxt.txt) or construct something like like a webfinger id nick@domain
(also used by mastodon etc.) from the domain and nick if there, else use domain as nick as well
@lyse@lyse.isobeef.org This looks like a nice way to do it.
Another thought: if clients canāt agree on the url (for example, if we switch to this new way, but some old clients still do it the old way), that could be mitigated by computing many hashes for each twt: one for every url in the feed. So, if a feed has three URLs, every twt is associated with three hashes when it comes time to put threads together.
A client stills need to choose one url to use for the hash when composing a reply, but this might add some breathing room if thereās a period when clients are doing different things.
(From what I understand of jenny, this would be difficult to implement there since each pseudo-email can only have one msgid to match to the in-reply-to headers. I donāt know about other clients.)
@movq@www.uninformativ.de Another idea: just hash the feed url and time, without the message content. And donāt twt more than once per second.
Maybe you could even just use the time, and rely on @-mentions to disambiguate. Not sure how that would work out.
Though I kind of like the idea of twts being immutable. At least, itās clear which version of a twt youāre replying to (assuming nobody is engineering hash collisions).
@movq@www.uninformativ.de @prologic@twtxt.net Another option would be: when you edit a twt, prefix the new one with (#[old hash]) and some indication that itās an edited version of the original tweet with that hash. E.g. if the hash used to be abcd123, the new version should start ā(#abcd123) (redit)ā.
What I like about this is that clients that donāt know this convention will still stick it in the same thread. And I feel itās in the spirit of the old pre-hash (subject) convention, though thatās before my time.
I guess it may not work when the edited twt itself is a reply, and there are replies to it. Maybe that could be solved by letting twts have more than one (subject) prefix.
But the great thing about the current system is that nobody can spoof message IDs.
I donāt think twtxt hashes are long enough to prevent spoofing.
@prologic@twtxt.net One of your twts begins with (#st3wsda): https://twtxt.net/twt/bot5z4q
Based on the twtxt.net web UI, it seems to be in reply to a twt by @cuaxolotl@sunshinegardens.org which begins āIāve been sketching outā¦ā.
But jenny thinks the hash of that twt is 6mdqxrq. At least, thereās a very twt in their feed with that hash that has the same text as appears on yarn.social (except with ā instead of ā).
Based on this, it appears jenny and yarnd disagree about the hash of the twt, or perhaps the twt was edited (though I canāt see any difference, assuming ā vs ā is just a rendering choice).
@prologic@twtxt.net How does yarn.socialās API fix the problem of centralization? I still need to know whose API to use.
Say I see a twt beginning (#hash) and I want to look up the start of the thread. Is the idea that if that twt is hosted by a a yarn.social pod, it is likely to know the thread start, so I should query that particular pod for the hash? But what if no yarn.social pods are involved?
The community seems small enough that a registry server should be able to keep up, and I can have a couple of others as backups. Or I could crawl the list of feeds followed by whoever emitted the twt that prompted my query.
I have successfully used registry servers a little bit, e.g. to find a feed that mentioned a tag I was interested in. Was even thinking of making my own, if I get bored of my too many other projects :-)
@movq@www.uninformativ.de Thanks, it works!
But when I tried it out on a twt from @prologic@twtxt.net, I discovered jenny and yarn.social seem to disagree about the hash of this twt: https://twtxt.net/twt/st3wsda . jenny assigned it a hash of 6mdqxrq but the URL and prologicās reply suggest yarn.social thinks the hash is st3wsda. (And as a result, jenny āfetch-context didnāt work on prologicās twt.)
@prologic@twtxt.net Yes, fetching the twt by hash from some service could be a good alternative, in case the twt I have does not @-mention the source. (Besides yarnd, maybe this should be part of the registry API? I donāt see fetch-by-hash in the registry API docs.)
@movq@www.uninformativ.de you said you liked seeing the hash (which is a fair choice!). All I am asking is for a reconsideration as a user configurable feature. ;-) It looks redundant, in my opinion.
@movq@www.uninformativ.de, that would be a nice addition. :-) I would also love the ability to hide/not show the hash when reading twtxts (after all, thatās on the header on each āemailā). Could that be added as a user configurable toggle?
password is generated using caddy hash-password
yarnd does not do auto discovery via webfinger though.. i cant put @username and have it fetch the feed url from webfinger. to fully make feeds portable. would also need to be able to use that for hashing.
>
?
@sorenpeter@darch.dk this makes sense as a quote twt that references a direct URL. If we go back to how it developed on twitter originally it was RT @nick: original text
because it contained the original text the twitter algorithm would boost that text into trending.
i like the format (#hash) @<nick url> > "Quoted text"\nThen a comment
as it preserves the human read able. and has the hash for linking to the yarn. The comment part could be optional for just boosting the twt.
The only issue i think i would have would be that that yarn could then become a mess of repeated quotes. Unless the client knows to interpret them as multiple users have reposted/boosted the thread.
The format is also how iphone does reactions to SMS messages with +number liked: original SMS
@prologic@twtxt.net Iāve even added the twthash message hash to my Twtxt bash CLI script so I can properly answer here.
@prologic@twtxt.net was this in reply to a different thread? Or maybe a hash collision?
Iām not super a fan of using json. I feel we could still use text as the medium. Maybe a modified version to fix any weakness.
What if instead of signing each twt individually we generated a merkle tree using the twt hashes? Then a signature of the root hash. This would ensure the full stream of twts are intact with a minimal overhead. With the added bonus of helping clients identify missing twts when syncing/gossiping.
Have two endpoints. One as the webfinger to link profile details and avatar like you posted. And the signature for the merkleroot twt. And the other a pageable stream of twts. Or individual twts/merkle branch to incrementally access twt feeds.
@prologic@twtxt.net: I understand the benefits of using hashes, itās much easier to implement client applications (at the expense of ease of use without the proper client). I must say that I like the way the metadata extension is done. Simple and elegant! Itās hard to design simple things!
$name$
and then dispatch the hashing or checking to its specific format.
I have submitted this to be used as the hash tooling for Yarn. See it as a good example on using this in a production environment!
Logged in using new argon2i password hash!
$name$
and then dispatch the hashing or checking to its specific format.
Circling back to the IsPreferred method. A hasher can define its own IsPreferred method that will be called to check if the current hash meets the complexity requirements. This is good for updating the password hashes to be more secure over time.
func (p *Passwd) IsPreferred(hash string) bool {
_, algo := p.getAlgo(hash)
if algo != nil && algo == p.d {
// if the algorithm defines its own check for preference.
if ck, ok := algo.(interface{ IsPreferred(string) bool }); ok {
return ck.IsPreferred(hash)
}
return true
}
return false
}
https://github.com/sour-is/go-passwd/blob/main/passwd.go#L62-L74
example: https://github.com/sour-is/go-passwd/blob/main/pkg/argon2/argon2.go#L104-L133
$name$
and then dispatch the hashing or checking to its specific format.
Hold up now, that example hash doesnāt have a
$
prefix!
Well for this there is the option for a hash type to set itself as a fall through if a matching hash doesnāt exist. This is good for legacy password types that donāt follow the convention.
func (p *plainPasswd) ApplyPasswd(passwd *passwd.Passwd) {
passwd.Register("plain", p)
passwd.SetFallthrough(p)
}
https://github.com/sour-is/go-passwd/blob/main/passwd_test.go#L28-L31
$name$
and then dispatch the hashing or checking to its specific format.
Here is an example of usage:
func Example() {
pass := "my_pass"
hash := "my_pass"
pwd := passwd.New(
&unix.MD5{}, // first is preferred type.
&plainPasswd{},
)
_, err := pwd.Passwd(pass, hash)
if err != nil {
fmt.Println("fail: ", err)
}
// Check if we want to update.
if !pwd.IsPreferred(hash) {
newHash, err := pwd.Passwd(pass, "")
if err != nil {
fmt.Println("fail: ", err)
}
fmt.Println("new hash:", newHash)
}
// Output:
// new hash: $1$81ed91e1131a3a5a50d8a68e8ef85fa0
}
This shows how one would set a preferred hashing type and if the current version of ones password is not the preferred type updates it to enhance the security of the hashed password when someone logs in.
https://github.com/sour-is/go-passwd/blob/main/passwd_test.go#L33-L59
I made a thing. Its a multi password type checker. Using the PHC string format we can identify a password hashing format from the prefix $name$
and then dispatch the hashing or checking to its specific format.
Tell me you write go like javascript without telling me you write go like javascript:
import "runtime/debug"
var Commit = func() string {
if info, ok := debug.ReadBuildInfo(); ok {
for _, setting := range info.Settings {
if setting.Key == "vcs.revision" {
return setting.Value
}
}
}
return ""
}()
@movq@www.uninformativ.de, any plans still to clean up the hash from the twtxtās body? Maybe a Festivus gift? You know, āfor the rest of usā. :-D
@movq@www.uninformativ.de was the request to remove the hash (subject) from showing on twts discarded? I donāt see it on the TODO, so I am curious. Was it something you decided was not worth investing time on?
@movq@www.uninformativ.de, is removing the hash from the body of the twt on the TODO? I read it, but I am unsure if it is there already, or not. š Sorry if it is, and I failed to spot it!
@movq@www.uninformativ.de You can always use a 5GB video file if the UI hashes it with SHA512 before posting to the server.
@movq@www.uninformativ.de
With those two (Message-ID, and In-Reply-To) the hashing could become superfluous, and no longer needed. I would vote for that!
I am noticing that Yarn doesnāt treat āoutsideā (that is, twts coming from a client other than Yarn) twts hashes right. Two examples:
There are many more, but those two will give you the gist. Yarn links the hash to the posterās twtxt.txt, so conversation matching will not work.
So I should really try setting up a Restic repo on an IPFS/IPNS hash.
No, Iām still doing them manually. š¤£š¤¦š» But I do think they are a good idea and will be adding them, I just havenāt gotten around to finding a compatible implementation of the hash yet.
@prologic@twtxt.net @anth Sounds like a good idea. The hash to conv/search url should stay local to a pod.
@movq@www.uninformativ.de No argument that threading is an improvement. But I think (#hash) does that, and I think figuring out how to search should mostly be up to the client.
@prologic@twtxt.net i think i finally sussād out my hash issue.. now to figure out why im losing avatars on restart.
Okay, a bit better: it now preserves the author, although it prints a hash right now. Tomorrowās problem.
@prologic@twtxt.net yeah it reads a seed file. Iām using mine. it scans for any mention links and then scans them recursively. it reads from http/s or gopher. i donāt have much of a db yet.. it just writes to disk the feed and checks modified dates.. but I will add a db that has hashs/mentions/subjects and such.
@prologic@twtxt.net do you have any info on how the ā!ā tags are supposed to work? are they just a different kind of hash tag?
@prologic@twtxt.net just an off the wall question about hashes. why not use the time+message as it was in the original twtxt.txt file? is it because itās just not store anyplace?
also how set in stone is using user+url? vs user@domain? the latter would mean the url could change without invalidating the hash.
@prologic@twtxt.net Web Key Directory: a way to self host your public key. instead of using a central system like pgp.mit.net or OpenPGP.org you have your key on a server you own.
it takes an email@address.com hashes the part before the @ and turns it into [openpgpkey.]address.com/.well-known/openpgpkey[/address.com]/<hash>
@prologic@twtxt.net huh.. true.. the email is md5/sha256 before storing.. if twtxt acted as provider you would store that hash and point the SRV record to the pod. .. to act as a client it would need to store the hash and the server that hosts the image.
Beating hash tables with trees? The ART-ful radix trie https://www.the-paper-trail.org/post/art-paper-notes/
Prospecting for Hash Functions Ā« null program https://nullprogram.com/blog/2018/07/31/
Fibonacci Hashing: The Optimization that the World Forgot (or: a Better Alternative to Integer Modulo) | Probably Dance https://probablydance.com/2018/06/16/fibonacci-hashing-the-optimization-that-the-world-forgot-or-a-better-alternative-to-integer-modulo/
A new fast hash table in response to Googleās new fast hash table | Probably Dance https://probablydance.com/2018/05/28/a-new-fast-hash-table-in-response-to-googles-new-fast-hash-table/
Bad idea of the day: A browser extension that links everything in your browser cache with a fake file whose name is a hash of that item, serves those fake files over bittorrent, and, for all URLs whose expiration date is in the future, keeps a distributed table of URL to hash & attempts to fetch from bittorrent before from http
The False Allure of Hashing for Anonymization https://gravitational.com/blog/hashing-for-anonymization/
Bad idea of the day: an extension that renders every word in a font chosen based on the hash of that word
Bad idea of the day: Instead of ads mining bitcoins in your browser, they run IPFS nodes and pin arbitrary hashes in browser persistent storage then store them.
Too Many Requests https://www.reddit.com/r/ProgrammerHumor/comments/78aa07/reddit_host_a_joke_etcpasswd_with_hashes_for/dosn53u/?context=1