🐉 🗡️ 🔮 ⚒️ 👻 🧛‍♀️ 🦇 🛡️ 👑 $8

I’m a senior web developer doing non-profit work in juvenile justice, a tai chi teacher, and a home/public school mom to a couple of wonderful children.

Current Quests

👩‍💻Coding ☯️Tai Chi 🐸Lillihub

📜 Adventure Log

February 20, 2024

Some lessons, like keeping footware dry, I fear my kids will never learn…

Girl on crutches at the beach in winter. She is placing her feet in the water. She is wearing red slippers.

February 15, 2024

I’m having some fun with the new Micro.blog premium feature, private notes. I’m trying to figure out what parts of my workflow I can move over 😄

screenshot of the new notes UI in Micro.blog with three notes showing

 #productivity

February 14, 2024

Currently reading: When Your Child Hurts by Rachael Coakley 📚

February 13, 2024

Back to Boston Children’s with my daughter. Since the winter storm is upon us and the other patients canceled, I’m hoping the appointment will go a bit quicker than the scheduled five hours. Hopefully the snow isn’t too bad when we head out. ❄️

February 12, 2024

Private key (AES-CBC) encryption and decryption in Deno

I found myself needing to encrypt a small string on Deno (and subsequently decrypt it later) for a small side project. I checked out a few websites with code samples. But those didn’t work/were out of date. So this is what worked for me:

Note: I am not a security expert and I don’t play one on TV. You shouldn’t trust anything important with random code you found on the internet. Seriously.

1. Save the key

First we generate a key using the standard SubtleCrypto api that ships with Deno. Then export a JSON webkey and save it. I’m putting it in an environmental variable. Make sure it is safe and secure.


const key = await crypto.subtle.generateKey({ name: "AES-CBC", length: 128 },true,["encrypt", "decrypt"]);
const rawKey = JSON.stringify(await crypto.subtle.exportKey("jwk", key));

2. Encrypt a string

Here we take the JSON webkey from our environmental variable that we created in step one and import it. Then using the key along with some random bytes, the initialization vector iv, we encrypt the string. The last two lines deal with getting the encrypted string into a format to save. The iv needs to be random and unique per message but it doesn’t need to be secret. So we can prepend it to the encrypted message.

You could potentially take this one step further and get a hex string from the encrypted bytes and save that. But for my needs I stopped here and stored the comma separated string of numbers.


async function encryptMe(decrypted)
{
    const _appSecret = JSON.parse(Deno.env.get("APP_SECRET"));
    const iv = await crypto.getRandomValues(new Uint8Array(16)); 
    const key = await crypto.subtle.importKey("jwk", _appSecret, "AES-CBC", true, ["encrypt", "decrypt"]);
    const encrypted = await crypto.subtle.encrypt({name: "AES-CBC", iv}, key, new TextEncoder().encode(decrypted));
    const encryptedBytes = new Uint8Array(encrypted);
    return `${iv.toString()}|${encryptedBytes.toString()}`;
}

3. Decrypt a string

The next step is to decrypt a string we previously encrypted. After we make a key we will need to separate out the two parts of the passed in message. The first part specifies the iv that was used and the second stores the encrypted message. You can use the Uint8Array.from to re-create the Unit8Array. Then call the decrypt method from the key, use a text decoder and you have your decrypted message. Yay! 👏


async function decryptMe(encrypted) 
{
    const _appSecret = JSON.parse(Deno.env.get("APP_SECRET"));
    const key = await crypto.subtle.importKey("jwk", _appSecret, "AES-CBC", true, ["encrypt", "decrypt"]);
    const ivPart = encrypted.split('|')[0];
    const encryptedPart = encrypted.split('|')[1];

    const encryptedBytes = Uint8Array.from(encryptedPart.split(',').map(num => parseInt(num)));
    const iv = Uint8Array.from(ivPart.split(',').map(num => parseInt(num)));
    
    const decrypted = await crypto.subtle.decrypt({name: "AES-CBC", iv}, key, encryptedBytes);
    const decryptedBytes = new Uint8Array(decrypted);
    return new TextDecoder().decode(decryptedBytes);
}

Permission noticeTHE CODE SAMPLE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE CODE SAMPLE OR THE USE OR OTHER DEALINGS WITH THE CODE SAMPLE.

 #code

February 11, 2024

This morning I accidentally used mint extract instead of vanilla extract in my berry crisp 🤦

February 3, 2024

I want to thank seventeen year old me for trying out Tai Chi. I want to thank all the versions of me that kept with it. There are few things that make me feel so at peace. I let the world pass me by and I simply move with the forms.

 #tai chi

January 27, 2024

It’s been a hard and long week. My daughter’s knee injury had an unexpected prognosis and its been tough to wrap my head around it. She’ll be all right, it’s just that the path to get there is longer and the way forward is murky.

January 20, 2024

Family game night ❤️

adult and two children playing the board game Wingspan on a kitchen table

January 18, 2024

My son and I have had friction homeschooling this year. So yesterday morning we spent two hours brainstorming what to do and when he was last really happy with school. Turns out he was happiest when he read all the time. So we’re adjusting and adding in his wonderful choices ❤️📚

A pile of books on a table. Books are a variety of nonfiction and fiction texts including titles like the “Once and Future King” and “Charles Darwin and the Voyage of the Beagle”

 #homeschooling