The US economy added 162,000 jobs last month, exceeding expectations. https://www.bls.gov/news.release/empsit.nr0.htm
@newsguyusa At this point, I dont believe any stats coming from the feds, they are just cooking the books!
Discussion
The US economy added 162,000 jobs last month, exceeding expectations. https://www.bls.gov/news.release/empsit.nr0.htm
@newsguyusa At this point, I dont believe any stats coming from the feds, they are just cooking the books!
The US economy added 162,000 jobs last month, exceeding expectations. https://www.bls.gov/news.release/empsit.nr0.htm
RE: https://mathstodon.xyz/@MartinEscardo/117209389235659699
Rich people are awful new study found!😂
“The general pattern seems to be that with wealth and rising power, you become less engaged with the needs of others and less burdened by the needs of social relationships,”
This NAS company wants to run your local smart home
https://www.theverge.com/tech/990006/this-nas-company-wants-to-run-your-local-smart-home?utm_source=flipboard&utm_medium=activitypub
Posted into Tech News @tech-news-theverge
Hi friends! New from me this week. Didn’t think I’d make this date, what with all the house stuff, but here it is! The final part of the Run, Hide, Seek, Find tetralogy:
Bandcamp:
https://synaptyx.bandcamp.com/album/find
Subvert: https://www.subvert.fm/synaptyx/find
Mirlo: https://www.subvert.fm/synaptyx/find
JamCoop: https://jam.coop/artists/synaptyx/albums/find
#BandcampFriday #Bandcamp #Subvert #Mirlo #JamCoop #ElectronicMusic #NewAlbum #Music #Electronica #Ambient #Downtempo #Techno #Breakbeat #Electronic @electronicmusic
This rugged phone’s removable camera can survive and capture your extreme adventures
https://www.theverge.com/tech/989657/rugone-xsnap-7-pro-smartphone-removable-action-camera-rugged-waterproof?utm_source=flipboard&utm_medium=activitypub
Posted into Tech News @tech-news-theverge
Lexar’s Muse is an ultra-slim portable SSD that’s less than 4mm thick
https://www.theverge.com/tech/986960/lexar-muse-ultra-thin-ssd-storage-drive-proprietary-cable?utm_source=flipboard&utm_medium=activitypub
Posted into Tech News @tech-news-theverge
Non abbiamo alcuna speranza di controllare ciò che fanno le Big Tech, ma c'è una cosa su cui abbiamo il controllo totale e assoluto: ciò che facciamo. Non dobbiamo permettere alle aziende americane di ricorrere ai nostri tribunali per chiudere le nostre aziende quando screditano i loro prodotti difettosi. Le nostre leggi sono sotto il controllo totale e definitivo del nostro paese. Se abroghiamo il recepimento del DMCA statunitense e legalizzeremo il jailbreak, libereremo i nostri tecnologi e imprenditori, e faremo a meno di quei prodotti americani scadenti.
This Is For Everyone is now available in paperback.
You might recognise the face on the cover...a younger me at MIT in 1998 when 150 million people used the web. Today it's roughly 6 billion.
Read about how the web came to be and where I think it's going ➡️ https://thisisforeveryone.timbl.com/
How Sonos rebooted itself
https://www.theverge.com/podcast/988368/sonos-ceo-tom-conrad-ai-smart-home-fabric-app-redesign?utm_source=flipboard&utm_medium=activitypub
Posted into Tech News @tech-news-theverge
« Ne pas utiliser Firefox » : l’aveu caché d’un code mal fichu
Après Bluesky, Goodtech.info s’installe dans le Fediverse et arrive sur Mastodon
If you're reading this, you've probably been hitting your head against a brick wall trying to parse and decipher the new HTTP Signatures sent by Mastodon and other Fediverse servers.
This is a basic and somewhat incomplete guide to accepting these signatures. I'm sure there are various gotchas, but it works with the signatures I've seen in the wild.
OK, wow, no need to be a dick about it! Here's how I validated a real signature that my server received.
PHP
$verified = openssl_verify( data: '"@method": POST"@target-uri": https://example.viii.fi/inbox"content-digest": sha-256=:tFdB/ENGczHMlZMDb66pXoUi2d0OqH2iBHdnN/WV1mc=: "@signature-params": ("@method" "@target-uri" "content-digest");created=1787780262;keyid="https://mastodon.social/users/Edent#main-key"', signature: base64_decode( "sIfmNsM/Q8iG6AJlne1IkZVjQSVFDEYIPsnoSOXQY+W3Eb4+SOn9o4J5SQmFOP+Jecjf3ioFwUdsrFjAGkUUOHPvSbNWkGKtNuGm+C6r3aI3JBCFGPqX3ITgZYV76CF7JJJ5hPGaG8YH/XdmxVIeFfD3M39FQCncMyyq7xJJvwKKP1mzS5s1vNQie8hbQ9owRjtqvoWcmM9GEYCUHNcMPLjZc+CBrj8sfBbNTYgIFI4UtirOaRJvYymxXjmXuzeVYxQujMjAjgobxQ8QFv0zlYsHk+gS5EYyafpJG9zmfCFSoF9+ZwqKNADmuADbISD9LZIH/bmkPoNXhxaeFPqYog==" ), public_key: "-----BEGIN PUBLIC KEY-----\nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAsYMEs4waqk/6gaS+xn1T\nYygElTtNIFNkBcEdEBMaeoGVhyZiVKtSjJCS4z+X+394PKvcfSTcFILIt2GI2jOB\nHD0M2fFgxc8mmdSdCQkgEh9jF3bFI3kopDvzYf726iioYKlHXKpfPKvFt7EJgKH7\naCtS25NQkek3YUd6y3VBcT3R6Xhze9P3QNoZMIsFXklgXDKj+EllfbUqLf1vxt3s\nmD9ETxy2bJi9FheE0uY2WhARn49XAvwczM5Wzt+zqxVEtgpi5v2+ZZAVKhDnJkiC\nCCuI6hrSnKNIx/5mSlX0a0S5h5d03djrCkYsqmwelu01rhOXP2grsz4BXp0y2wrO\n3QIDAQAB\n-----END PUBLIC KEY-----\n", algorithm: "sha256" ); echo $verified;
Copy and paste that into PHP and you should see that $verified is true.
Say please.
Along with the message sent to your server, you will have received HTTP headers like this:
![]()
content-digest: sha-256=:tFdB/ENGczHMlZMDb66pXoUi2d0OqH2iBHdnN/WV1mc=: signature: sig1=:sIfmNsM/Q8iG6AJlne1IkZVjQSVFDEYIPsnoSOXQY+W3Eb4+SOn9o4J5SQmFOP+Jecjf3ioFwUdsrFjAGkUUOHPvSbNWkGKtNuGm+C6r3aI3JBCFGPqX3ITgZYV76CF7JJJ5hPGaG8YH/XdmxVIeFfD3M39FQCncMyyq7xJJvwKKP1mzS5s1vNQie8hbQ9owRjtqvoWcmM9GEYCUHNcMPLjZc+CBrj8sfBbNTYgIFI4UtirOaRJvYymxXjmXuzeVYxQujMjAjgobxQ8QFv0zlYsHk+gS5EYyafpJG9zmfCFSoF9+ZwqKNADmuADbISD9LZIH/bmkPoNXhxaeFPqYog==: signature-input: sig1=("@method" "@target-uri" "content-digest");created=1787780262;keyid="https://mastodon.social/users/Edent#main-key"
The signature-input tells you how to construct a "Signature Base". You have to build a text string which places the various components in the order specified and separated with a newline:
![]()
"@method": POST "@target-uri": https://example.viii.fi/inbox "content-digest": sha-256=:tFdB/ENGczHMlZMDb66pXoUi2d0OqH2iBHdnN/WV1mc=: "@signature-params": ("@method" "@target-uri" "content-digest");created=1787780262;keyid="https://mastodon.social/users/Edent#main-key"
Where @method is the HTTP method used to send data to your server (usually GET or POST), and @target-uri is the URl the message was sent to (usually your inbox).
The publicKey is slightly trickier. As you can see, the signature-input ends with keyid="https://mastodon.social/users/Edent#main-key
If you make a signed request to that URl, you'll get back an ActivityPub Actor document. It will look something like this:
JSON
{ "@context": [ "https://www.w3.org/ns/activitystreams", "https://w3id.org/security/v1", ], "id": "https://mastodon.social/users/Edent", "webfinger": "Edent@mastodon.social", "type": "Person", "name": "Terence Eden", "publicKey": { "id": "https://mastodon.social/users/Edent#main-key", "owner": "https://mastodon.social/users/Edent", "publicKeyPem": "-----BEGIN PUBLIC KEY-----\nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAsYMEs4waqk/6gaS+xn1T\nYygElTtNIFNkBcEdEBMaeoGVhyZiVKtSjJCS4z+X+394PKvcfSTcFILIt2GI2jOB\nHD0M2fFgxc8mmdSdCQkgEh9jF3bFI3kopDvzYf726iioYKlHXKpfPKvFt7EJgKH7\naCtS25NQkek3YUd6y3VBcT3R6Xhze9P3QNoZMIsFXklgXDKj+EllfbUqLf1vxt3s\nmD9ETxy2bJi9FheE0uY2WhARn49XAvwczM5Wzt+zqxVEtgpi5v2+ZZAVKhDnJkiC\nCCuI6hrSnKNIx/5mSlX0a0S5h5d03djrCkYsqmwelu01rhOXP2grsz4BXp0y2wrO\n3QIDAQAB\n-----END PUBLIC KEY-----\n" },
The publicKeyPem is the string you need. There's no need to convert the \n to literal newlines.
Not quite! All we've done so far is verify the headers. It is possible that these are genuine headers but attached to a fraudulent body.
This takes us back to the header "content-digest": sha-256=:tFdB/ENGczHMlZMDb66pXoUi2d0OqH2iBHdnN/WV1mc=:
That says that the body of the message sent has a Base64 encoded SHA256 hash of tFdB/ENGczHMlZMDb66pXoUi2d0OqH2iBHdnN/WV1mc=.
To calculate your own content digest in PHP:
PHP
$input = file_get_contents( "php://input" ); $digestCalculated = base64_encode( hash( algo: "sha256", data: $input, binary: true ) );
Does your digest match the one sent along with the headers? If not, something dodgy is going on.
The steps are:
content-digest extract the algorithm and hash.content-digest.signature extract the base64 encoded signature.signature-input extract the signature-input string.openssl_verify() to verify the Signature Base and the base64 decoded signature, against the Public Key using SHA256.Note, Mastodon only uses SHA256. I think it should explicitly say which algorithm it is using and have raised the issue.
This is how you do it in PHP. Please read this carefully as there are some hard-coded assumptions.
PHP
<?php// Validate the Digest.// It is the hash of the raw input string, in binary, encoded as base64.// The format is content-digest => <algorithm>=:<base64 encoded hash>:$digestString = $headers["content-digest"]; // The Base64 encoding may have multiple `=` at the end. So split this at the first `=`.$digestData = explode( separator: "=", string: $digestString, limit: 2 ); // Hashes are in lowercase, but have a `-` in their name.// This is not what hash_algos() expects.$digestAlgorithm = str_replace( search: "-", replace: "", subject: $digestData[0] ); // The hash is surrounded by `:` characters.$digestHash = str_replace( search: ":", replace: "", subject: $digestData[1] ); // Check if the hash algorithm is one known about to PHP.// If not, reject and record an error.if ( !in_array( needle:$digestAlgorithm, haystack: hash_algos() ) ) { return false; } // Manually calculate the digest based on the data sent.$digestCalculated = base64_encode( hash( algo: $digestAlgorithm, data: $input, binary: true ) ); // Does our calculation match what was sent?if ( !( $digestCalculated == $digestHash ) ) { return false; } // The signature format is signature => <signature name>=:<base64 encoded hash>:$signatureString = $headers["signature"]; // The Base64 encoding may have multiple `=` at the end. So split this at the first `=`.$signatureData = explode( separator: "=", string: $signatureString, limit: 2 ); $signatureName = $signatureData[0]; // The signature is surrounded by `:` characters.$signatureB64 = str_replace( search: ":", replace: "", subject: $signatureData[1] ); // The signature-input format is complicated!$signatureInputString = $headers["signature-input"]; // Get the parameters. Assume there is only one signature.$signatureParamsString = explode( separator: "=", string: $signatureInputString, limit: 2 )[1]; // Get the different elements of the signature.$signatureInputData = explode( separator: ";", string: $signatureInputString ); // Construct the data.$signatureInput = []; foreach( $signatureInputData as $signatureInputParts ) { $partsData = explode( separator: "=", string: $signatureInputParts ); // Strip quotes from keyid and parentheses from sig1. if ( "keyid" == $partsData[0] ) { $partsData[1] = str_replace( search: "\"", replace: "", subject: $partsData[1] ); } if ( $signatureName == $partsData[0] ) { $partsData[1] = str_replace( search: ["(", ")"], replace: "", subject: $partsData[1] ); } $signatureInput[ $partsData[0] ] = $partsData[1] ; } $signatureStructure = $signatureInput[$signatureName]; $signatureKeyID = $signatureInput["keyid"]; // Remove quotes.$signatureStructure = str_replace( search: "\"", replace: "", subject: $signatureStructure ); $signatureStructureData = explode( separator: " ", string: $signatureStructure ); // https://www.rfc-editor.org/info/rfc9421/#section-2.5$signatureBase = ""; foreach ( $signatureStructureData as $signatureStructureParts ) { if ( "@method" == $signatureStructureParts ) { // https://www.rfc-editor.org/info/rfc9421/#name-method $signatureBase .= "\"@method\": " . $_SERVER["REQUEST_METHOD"] . "\n"; } if ( "@target-uri" == $signatureStructureParts ) { // https://www.rfc-editor.org/info/rfc9421/#section-2.2.2 // Change the domain name to your own. $signatureBase .= "\"@target-uri\": https://EXAMPLE.COM" . $_SERVER["REQUEST_URI"] . "\n"; } if ( "content-digest" == $signatureStructureParts ) { $signatureBase .= "\"content-digest\": $digestString\n"; } } // https://victoronsoftware.com/posts/http-message-signatures/#how-the-signature-is-created$signatureBase .= "\"@signature-params\": $signatureParamsString"; // Get the signing user's public key.// This is usually in the form `https://example.com/user/username#main-key`// This is to differentiate if the user has multiple keys.// This may need to be a signed request. You will need to write your own getDataFromURl() function to get the sending user's key.$userData = getDataFromURl( $signatureKeyID ); $publicKey = $userData["publicKey"]["publicKeyPem"]; // Verify the request$verified = openssl_verify( data: $signatureBase, signature: base64_decode( $signatureB64 ), public_key: $publicKey, algorithm: $digestAlgorithm ); // Convert the result to boolean.if ( $verified === 1 ) { $verified = true; } elseif ( $verified === 0 ) { $verified = false; } else { $verified = null; } return $verified;
This blog post was funded in part by the work I'm doing for my NLnet NGI0 grant. Thanks!
#ActivityBot #ActivityPub #mastodon #php #webdevSwitchBot’s retrofit door lock offers 19 ways to unlock it
https://www.theverge.com/tech/989246/switchbot-lock-ultra-max-retrofit-smartlock-ifa-launch?utm_source=flipboard&utm_medium=activitypub
Posted into Tech News @tech-news-theverge
Here’s the first 4K 120Hz UST projector with optical lens shift
https://www.theverge.com/gadgets/986005/awol-visions-4k-120hz-ust-projector-is-first-with-optical-lens-shift?utm_source=flipboard&utm_medium=activitypub
Posted into Tech News @tech-news-theverge
Philips Hue adds more affordable options for syncing smart lights with your TV
https://www.theverge.com/tech/988363/philips-hue-play-screen-sync-entertainment-lighting?utm_source=flipboard&utm_medium=activitypub
Posted into Tech News @tech-news-theverge
Anker put a display on the case of its new sleepbuds
https://www.theverge.com/tech/988265/anker-sleep-earbuds-4-pro-price-date-specs?utm_source=flipboard&utm_medium=activitypub
Posted into Tech News @tech-news-theverge
Now you can tell the Hue app how you want your smart lights to work
https://www.theverge.com/tech/988953/philips-hue-smart-lighting-custom-ai-behaviors-sonos-integration?utm_source=flipboard&utm_medium=activitypub
Posted into Tech News @tech-news-theverge
I want to wrap myself in Hue’s new Liane rope lights
https://www.theverge.com/tech/989014/philips-hue-liane-360-rope-lights-smart-lighting-interior-design?utm_source=flipboard&utm_medium=activitypub
Posted into Tech News @tech-news-theverge
RE: https://mamot.fr/@ploum/117202338350731080
One of the benefits of daily-driving @postmarketOS is that you do have a smartphone but the crappy apps are not available for anything outside the Android/iOS duopoly. It's a great conversation starter about lock-in, sovereignty, software freedom etc.