Damus
144MB profile picture
144MB
@144MB

I sign Floppy PNGs with the same private key associated with this npub.

My entire software repo is inside my banner PNG. It can be extracted with this script:

Deno.writeFileSync("f.z",Deno.readFileSync("f.png").slice(41,-16))
new Deno.Command('pigz',{args:['-d','-f','-k','f.z']}).outputSync()
let extracted_data=Deno.readFileSync('f')
const data_length=parseInt(new TextDecoder().decode(extracted_data.slice(65,4120)).split('\n')[0])
const unfiltered=new Uint8Array(extracted_data.length)
let f=0,p=0,r=0
do{if(r==4140||f==0){f++;r=0;} else {unfiltered[p]=extracted_data[f];r++;f++;p++;}}while(f<extracted_data.length)
let site_text=(new TextDecoder().decode(unfiltered.slice(542340,542340+data_length)))
Deno.writeTextFileSync('site.txt',site_text)

This should be verified. I sign the data part of the PNG and use the top row to store the secp256k1 signature. This can be verified with this script:

import { sha256 } from "@noble/hashes/sha2";
import { schnorr } from "@noble/curves/secp256k1";
import * as pako from "pako";
try {
let f = 0, p = 0, r = 0;
const fpng_img = Deno.readFileSync(Deno.args[0]);
const pub = Deno.readTextFileSync(Deno.args[1]).trim();
const zdat = pako.inflate(fpng_img.slice(41, -16));
const u = new Uint8Array(zdat.length);
do {
if (r == 4140 || f == 0) {
f++;
r = 0;
} else {
u[p] = zdat[f];
r++;
f++;
p++;
}
} while (f < zdat.length);
const dl=parseInt(new TextDecoder().decode(zdat.slice(65,4140)).split('\n')[0])
console.log(schnorr.verify(
new Uint8Array(zdat.slice(1, 65)),
sha256(u.slice(542340, dl + 542340)),
pub,
));
} catch {
console.log("Usage: lverify [Floppy PNG] [144MB Hex Public Key]");
}

The extract script itself can be extracted from the Floppy PNG using the instructions on the header of the banner of the PNG in my profile banner. It is all so wonderfully self-referential, no?

Note that to use the verify script you need something like this package.json:
{
"name": "anything",
"version": "1.0.0",
"dependencies": {
"@noble/curves": "^1.9.2",
"@noble/hashes": "^1.8.0",
"pako": "^2.1.0"
}
}

Later versions of noble/curves need a different import. Also, if you want to use that same site.txt file to load a web page, you can use this:

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Floppy PNG</title>
<meta name="viewport" content="width=device-width,initial-scale=1">
</head>
<body>
<div id="l"></div>
<script>
fetch('site.txt').then((resp) => {
resp.text().then((t)=>{
s = document.createElement("script");
s.appendChild(document.createTextNode(t));
document.body.appendChild(s);
})})
</script>
<div id="main"></div>
</body>
</html>

You need to remove the verify() command for it to work as a live web page. Verify the sig separately, remove the line, and spin up some kind of local web server. Most of the time the verify() command is the last line of site.txt. The web application for all browsers is listed in the floppypng.com repo (src/browser.js).

Relays (4)
  • wss://nos.lol/ – read & write
  • wss://relay.damus.io/ – read & write
  • wss://nostr.mom/ – read & write
  • wss://relay.primal.net/ – read & write

Recent Notes

Kip Ashlynn · 3d
My Vespa won't start 😭 The engine light is on, the engine chugs but won't turn over when I try and start it. My thoughts are 1) low fuel, the sensors have been a bit wonky so it might be that the...
144MB profile picture
Gasoline can get old. If you let it sit all winter, it won't fire as well, and will gum up your carb. If you add gas, charge the battery, and still have trouble, you might be able to get away with carb cleaner and completely new gas. If not, you'll have to rebuild the carb to clean the gunk out of it. Another thing to watch out for is water in the system that provides spark. You can verify that yourself by cranking with the plug out and grounded against the head (but do watch out for sloshed gasoline or vapors nearby!).
Helen Yrmom · 1w
You’re beyond help floppy. I would say if the peasant has no income, let him eat sats but you refuse to fully participate and set up a wallet. ⚡️👑
codonaft · 1w
"Who needs a slice of July sky?" (c) Egor Letov
codonaft · 1w
> pretty weird, true, but you have to admit that being able to store your software repo and app to view it as your banner image is pretty cool > We have these huge corporate-sponsored ecosystems with...
144MB profile picture
Did you remove the verify() at the end of site.txt? Since you are using a trimmed down bootloader and, pre-extracted/decoded data, you aren't using the same exact app as a normal site (floppypng.com). You can do that without an editor:

```
divine@l1g3r-srv-01:~/tmp$ head -n -1 site.txt > newsite.txt
divine@l1g3r-srv-01:~/tmp$ tail -n 2 newsite.txt
document.getElementById('main').innerHTML = site.rp['index-html'].replace('R0lGODdhAQABAIAAAP///////ywAAAAAAQABAAACAkQBADs=',site.logo);
refresh();
divine@l1g3r-srv-01:~/tmp$ tail -n 2 site.txt
refresh();
verify();
```
1💜1
codonaft · 1w
Oh, I got it; now it works, thanks!
Comte de Sats Germain · 2w
Ooooh I wanna make a Sumerian fish god hat and carry a trident or something
Laeserin · 2w
A lot of the EU is back in home office, again, or riding the bus or e-bike. Sales of e-cars are headed up, despite relatively moderate gasoline price increases. Let's get off oil, and stay off, guys....
144MB profile picture
I did a quick run-through of the threads on your post, and after 20 years of studying this, I recognize almost every comment... I've seen them all many times. All of them have their place and perspective that shows *a* truth. There is a bit of a Bateson double bind with these issues. Some of it is the way the responses are set up. Some of it is simply human capacity for analysis of large complex things. In other words, scale and complexity *must* be held up first, before tossing out stuff like biobutanol or the difference between a Ford flathead V8 from the 30s vs. a modern ICE. Comment-reply format like this simply can't progress for polycrisis stuff. It is a trap that makes people feel good about their stance, but it does little create a full cognitive map. Anything that comes close to a map that provides insight will be discarded quickly as too much. We demand single serving helpings (yes, Fight Club ref). Even then, the map is not the territory, sure, but tossing the whole thing to do comment-reply format? This is not better.

I was watching "In the Fires of Dead Stars" from the 2024 Dark Matter show, and recognized a bit of a cultural myth with Amanda's chosen reality. This is key. Myth doesn' t mean it can't be true. It just means that it is a cultural cognition shortcut that evades analysis (like complexity and scale). Our shared cultural cognition is the primary driver of our interactions, particularly these days. I admit that the dialog on this thread is much more sophisticated than I'm used to in the last five years or so, and the teams are more varied ( teams as defined by https://web.archive.org/web/20070418142809/http://groups.inf.ed.ac.uk/ppig/readinglist/tomasello_et_al2004.pdf ). It is one of the things I like about the Nostr crowd. BUT, it is the same rough layout, just more teams and better education.

The best resource I know of that brings somebody up to speed on these issues as far as scale is by Tom Murphy of UCSD:

https://escholarship.org/uc/item/9js5291m

Tom Murphy handles some complexity, but I'd probably start with fossil fuel feedstock flow and work backwards:

https://pubs.acs.org/doi/pdf/10.1021/acs.est.7b04573




👍1
Helen Yrmom · 2w
What in the medieval torture device? 🤣 Cool. Thanks for sharing.
codonaft · 2w
Just curious, what's the next step in your repo extraction quest after extracting the huge scary `site.txt`? It appears to be a frontend js without some ready way to load it. Verification script fail...
144MB profile picture
Below is a capture from my terminal, using the verify and extract scripts on this Nostr profile that you used. To answer your questions, pb.txt is a text file with my public key. It is the hex version of my Nostr npub ( ea91ee2eff0942115b5515bbdbee1259bcf899f8dc79b33d58524d104e3d5eb5). pb.txt is stored on all of my websites in the root. The huge, scary site.txt is appended to a web page inline, which I show below. I've done some performance tests, and besides making the PNG a standalone artifact with code and data and visual instructions, it performs surprisingly well vs. more traditional methods. It is scary, as it is code and data, which makes verification particularly important... but, really... not much scarier than visiting a website (but if you are running the scripts locally from a CLI, it is even more important to verify). As for the error with verify, unfortunately we live in a constantly changing world, so the imports change over time, but if you use package.json and pin the version, it works, or your patches work great, too for newer versions. These are the same versions of noble curves/hashes I have in my repo package.json, but, of course, there is a catch-22 if you are extracting the repo itself (on floppypng.com). Note that I verify the floppy PNG as part of the web app. I verify against the original extract of the PNG in the application, but with the simplified version below, I don't capture these variables, so you need to remove the verify() at the end to view the site. Or, just use the same HTML from floppypng.com as a bootloader, and that works too. (curl https://floppypng.com).

```
divine@l1g3r-srv-01:~/tmp$ curl > f.png
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
100 1256k 100 1256k 0 0 7287k 0 --:--:-- --:--:-- --:--:-- 7304k
divine@l1g3r-srv-01:~/tmp$ vi ext.js
divine@l1g3r-srv-01:~/tmp$ deno run -A ext.js
divine@l1g3r-srv-01:~/tmp$ ls -l
total 14780
-rw-rw-r-- 1 divine divine 593 Apr 14 06:14 ext.js
-rw-rw-r-- 1 divine divine 6580049 Apr 14 06:15 f
-rw-rw-r-- 1 divine divine 1286599 Apr 14 06:12 f.png
-rw-rw-r-- 1 divine divine 1286542 Apr 14 06:15 f.z
-rw-rw-r-- 1 divine divine 5964092 Apr 14 06:15 site.txt
divine@l1g3r-srv-01:~/tmp$ vi package.json
divine@l1g3r-srv-01:~/tmp$ cat package.json
{
"name": "anything",
"version": "1.0.0",
"dependencies": {
"@noble/curves": "^1.9.2",
"@noble/hashes": "^1.8.0",
"pako": "^2.1.0"
}
}
divine@l1g3r-srv-01:~/tmp$ vi ver.js
divine@l1g3r-srv-01:~/tmp$ npm i
npm warn Unknown builtin config "globalignorefile". This will stop working in the next major version of npm.

added 3 packages, and audited 4 packages in 720ms

2 packages are looking for funding
run `npm fund` for details

found 0 vulnerabilities
divine@l1g3r-srv-01:~/tmp$ deno run -A ver.js
Usage: lverify [Floppy PNG] [144MB Hex Public Key]

divine@l1g3r-srv-01:~/tmp$ ls
ext.js f f.png f.z node_modules package.json package-lock.json pb.txt site.txt ver.js
divine@l1g3r-srv-01:~/tmp$ cat pb.txt
ea91ee2eff0942115b5515bbdbee1259bcf899f8dc79b33d58524d104e3d5eb5
divine@l1g3r-srv-01:~/tmp$ deno run -A ver.js f.png pb.txt
true
divine@l1g3r-srv-01:~/tmp$ cat page.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Floppy PNG</title>
<meta name="viewport" content="width=device-width,initial-scale=1">
</head>
<body>
<div id="l"></div>
<script>
fetch('site.txt').then((resp) => {
resp.text().then((t)=>{
s = document.createElement("script");
s.appendChild(document.createTextNode(t));
document.body.appendChild(s);
})})
</script>
<div id="main"></div>
</body>
</html>

divine@l1g3r-srv-01:~/tmp$ tail -n 3 site.txt
document.getElementById('main').innerHTML = site.rp['index-html'].replace('R0lGODdhAQABAIAAAP///////ywAAAAAAQABAAACAkQBADs=',site.logo);
refresh();
verify();
divine@l1g3r-srv-01:~/tmp$ vi site.txt
divine@l1g3r-srv-01:~/tmp$ npx http-server
Starting up http-server, serving ./

http-server version: 14.1.1

http-server settings:
CORS: disabled
Cache: 3600 seconds
Connection Timeout: 120 seconds
Directory Listings: visible
AutoIndex: visible
Serve GZIP Files: false
Serve Brotli Files: false
Default File Extension: none

Available on:
http://127.0.0.1:8080
http://192.168.52.51:8080
http://192.168.96.1:8080
http://192.168.149.1:8080
Hit CTRL-C to stop the server

[Tue Apr 14 2026 06:24:41 GMT-0700 (Pacific Daylight Time)] "GET /page.html" "Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:149.0) Gecko/20100101 Firefox/149.0"
(node:2678322) [DEP0066] DeprecationWarning: OutgoingMessage.prototype._headers is deprecated
(Use `node --trace-deprecation ...` to show where the warning was created)

```



Yeah... pretty weird, true, but you have to admit that being able to store your software repo and app to view it as your banner image is pretty cool, and shows the benefit of standalone artifacts. (Setting aside the fact that the current culture of software is an ever-changing, ever-more complex, ever-larger sea.) I don't think people appreciate how much you can do with 1.44MB. We have these huge corporate-sponsored ecosystems with millions of people running it. Layers on frameworks on layers on frameworks... for what? Burning up the biosphere for vertebrates even faster? We seem to love creating our own hell within hell within hell, hiding behind screens.
1💜1
codonaft · 1w
> pretty weird, true, but you have to admit that being able to store your software repo and app to view it as your banner image is pretty cool > We have these huge corporate-sponsored ecosystems with millions of people running it. Layers on frameworks on layers on frameworks... for what? Yeah, I t...
144MB profile picture
"Mom! Mom! Moooom! Mom!!!"

"I'm here darlin, what?"

"Come here, look what I made."

"What is it?"

"Look! Ecosystems, real local ecosystems. They even think they have free will!"

"Where did you launch?"

"Some random pale blue dot in the Milky Way"

"I never should have let you watch TV when you were a kid. It has warped your brain. I don't know why you feel attached to that particular galaxy. No wonder our energy bill was so high last week. Is your homework done?"

"No" <looks down, shuffles tentacles>

https://youtu.be/ZE1r5AWx4vc
5
codonaft · 2w
Just curious, what's the next step in your repo extraction quest after extracting the huge scary `site.txt`? It appears to be a frontend js without some ready way to load it. Verification script fails with `Error: "publicKey" expected Uint8Array of length 32, got type=string` for me. What's the pub...
CR45H 0V3RR1D3 · 1w
I still think she killed Kurt.