🍱 lowlighter’s standalone libraries
This is a collection of carefully crafted TypeScript standalone libraries. These try to be minimal, unbloated and convenient.
Most of them are written with deno in mind, but as the code honors web standards they should be usable on any runtime that follows web specifications (including browsers).
Index
- 🔳 QR Code generator
- 🔑 Time-based One-Time Password (TOTP)
- ➕ Diff (patience algorithm)
- 🔐 Symmetric encryption (using AES-GCM 256 with a PBKDF2 derived key)
These libraries are published at deno.land/x/libs.
Important
Love these bytes ? Consider 💝 sponsoring me
, even one-time contributions are greatly appreciated !
ℹ️ About
While this repository is open, it is not really intended to be a collaborative project. Pull requests for bug fixes or improvements are still welcome, but I may not accept any feature request if it doesn’t seem to fit the scope of this project.
Additionally, these libraries tends to follow my own coding style which:
- use ES next syntax
- try to be minimalistic and visually unbloated (no semicolons, infered typing, etc.)
- use caseless convention (single whole words are preferred assuming they’re unambiguous depending on the local context)
📜 License
This work is licensed under the MIT License.
If you include a significant part of it in your own project, you should keep the license notice with it, including the mention of the additional original authors if any.
📦 Libraries
🔳 QR Code generator
This library is based on the awesome work of @nayiki. Please take a look at their articles about QR Codes:
I rewrote this because I couldn’t find a suitable implementation using EcmaScript modules. Oddly enough, most of the libraries I found also required a <canvas>
to properly work (but I specifically wanted a SVG
image output). Usually it’s because they were maily intended for client-side usage. A few other implementations had either some dated code or obfuscated code which I didn’t want.
Features
- Support out-of-the-box
array
,console
andsvg
outputs - Customizable colors and error correction level (ECL)
- No external dependencies
- Not canvas based (i.e. no DOM dependencies and thus cross-platform)
Usage
import { qrcode } from "./qrcode.ts"
// SVG output
const svg = qrcode("https://example.com", { output: "svg" })
console.assert(svg.includes("</svg>"))
// Console output
qrcode("https://example.com", { output: "console" })
// Array output
const array = qrcode("https://example.com")
console.assert(Array.isArray(array))
🔑 Time-based One-Time Password (TOTP)
This library is based on the well-written article of @rajat-sr on hackernoon :
Their explanation was specifically intended for NodeJS so I rewrote it to make it compatible with native Web APIs. Additionally, the URL scheme for TOTP was implemented, and combined with the QR Code generator library it can be used to make it scannable with with an authenticator app such as Microsoft Authenticator or Google Authenticator.
Features
- Issue a new TOTP secret with metadata (issuer, account, image, etc.)
- No external dependencies
- Lightweight
Usage
import { otpauth, otpsecret, verify } from "./totp.ts"
import { qrcode } from "./qrcode.ts"
// Issue a new TOTP secret
const secret = otpsecret()
const url = otpauth({ issuer: "example.com", account: "alice", secret })
console.log(`Please scan the following QR Code:`)
qrcode(url.href, { output: "console" })
// Verify a TOTP token
const token = prompt("Please enter the token generated by your app:")!
console.assert(await verify({ token, secret }))
➕ Diff (patience algorithm)
This library is based on the previous work of @jonTrent which is itself based on the work of Bram Cohen.
I wrote this library because I’m working on a side project that allows edition of text content, and I wanted to implemente some kind of versioning system à la git. The thing is I didn’t want to create a binary dependency on a binary, especially since the tracked content are mostly small text that may be anywhere in the filesystem, including remote files which would have been outside boundaries of git versioning.
Note
patch()
is not implemented yet because I’m currently working on another personal project that I want to finish first (it’s actually the project that required both the QR code and the TOTP libraries) but it’ll eventually be available in the future.
Features
- Compute unified patch between two strings
- Match
diff
command line output - No external dependencies
- Lightweight
Usage
import { diff } from "./diff.ts"
// Print unified patch
console.log(diff("foo", "bar"))
--- a
+++ b
@@ -1 +1 @@
-foo
+bar
🔐 Symmetric encryption (using AES-GCM 256 with a PBKDF2 derived key)
This library is inspired by existing password managers, where the aim is to provide a secure way to store credentials at rest (for example in a Deno.Kv
store) while being able to recover them later using a single master key.
Here, it is achieved by using AES-GCM 256-bits
with PBKDF2
derived key. The latter could for instance use a username as salt
and a password as seed
to consistently forge back the
key and decrypt the stored credentials. These are provided by the native Web Crypto
APIs.
This library also adds additional features such as data integrity and original length obfuscation. It does not re-implement cryptographic primitives, it just provides a convenient way to use them.
Caution
As explained in the license:
THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND
The author is not responsible for any damage that could be caused by the use of this library. It is your responsibility to use it properly and to understand the security implications of the choices you make.
Features
- Use native
Web Crypto
APIs - Use
AES-GCM 256-bits
withPBKDF2
derived key to encrypt and decrypt messages- Encrypted messages are different each time thanks to initialization vector
- The derived key from a given
seed
/password
are always the same
- Added functionalities which also introduce additional entropy:
- With SHA-256 to guarantee integrity
- With stored size to guarantee integrity (for messages with length < 255)
- With padding to force length be
256
or512
bytes and obfuscate the original size (can be disabled using0
as value)
Usage
import { decrypt, encrypt, exportKey, importKey } from "./encryption.ts"
// Generate a key. Same seed and salt combination will always yield the same key
const key = await exportKey({ seed: "hello", salt: "world" })
console.assert(key === "664d43091e7905723fc92a4c38f58e9aeff6d822488eb07d6b11bcfc2468f48a")
// Encrypt a message
const message = "🍱 bento"
const secret = await encrypt(message, { key, length: 512 })
console.assert(secret !== message)
// Encrypted messages are different each time and can also obfuscate the original message size
console.assert(secret !== await encrypt(message, { key, length: 512 }))
console.assert(secret.length === 512)
// Decrypt a message
const decrypted = await decrypt(secret, { key })
console.assert(decrypted === message)