Sing-song: a speakable encoding for long numbers and keys

birdculture1 pts0 comments

Sing-song: a speakable encoding for long numbers and keys · blog.vrypan.net

blog.vrypan.net

This is a fun experiment that started as a way to generate deterministic "usernames" for<br>Nostr npub keys (see the last section).

English is really hard to deal with even<br>for simple syllables, so the result is not as good as I'd want it to be (a string you can<br>read to an other person over the phone and make sure they get it right), but it's not<br>bad either —if everyone spoke Itallian sing-song would be much more valuable :-)

Sing-song: speakable encodings for long numbers and keys

Status: draft, v0.1.2 --- comments welcome.

Abstract

Sing-song is a reversible encoding of arbitrary byte strings as<br>pronounceable CV syllables. Its 64-syllable alphabet maps each 6-bit<br>value directly to one syllable. Complete encodings preserve byte length<br>and leading zero bytes, require no external length metadata, and are<br>canonical.

The encoding is prefix-stable: shared input prefixes produce shared<br>syllable prefixes. An optional variant suffix provides alternative<br>reversible representations of the same byte string.

Motivation

Machine-oriented encodings such as hex and Base58 are compact but<br>awkward to speak, transcribe, and remember. Sing-song trades some<br>written density for a small, regular pronunciation grammar while<br>remaining deterministic, reversible, and computationally simple.

Design goals

The encoding should be deterministic , reversible ,<br>prefix-stable , speakable and transcribable without training,<br>self-sizing for complete byte strings, and self-delimiting<br>without load-bearing punctuation.

The encoding

Alphabet

Position<br>Symbols<br>Count

Consonant (odd )<br>b d f g j k l m n p r s t v w z<br>16

Vowel (even)<br>a i o u

Consonants and vowels strictly alternate, producing 64 open CV syllables<br>with no clusters or codas. Position parity determines the symbol table.<br>h, y, and e are omitted because their pronunciation is<br>comparatively unstable.

Syllables and grouping

Each syllable encodes exactly 6 bits. Display groups contain two<br>syllables (zila, sibo) separated by cosmetic hyphens.

Parsers MUST<br>ignore hyphens: zilasibotivajuzu and zila-sibo-tiva-juzu are<br>identical. Groups provide natural speaking checkpoints.

Pronunciation

Sing-song uses a fixed pronunciation for every letter. The spelling is phonemic: each letter represents one sound, and the same letter is always pronounced the same way.

The following IPA values are normative:

Letter

IPA<br>/a/<br>/i/<br>/o/<br>/u/<br>/b/<br>/d/<br>/f/<br>/ɡ/<br>/k/<br>/l/<br>/m/<br>/n/<br>/p/<br>/r/<br>/s/<br>/t/<br>/v/<br>/z/

Vowels are pure vowels and MUST NOT be interpreted according to English spelling conventions. In particular, i is /i/, o is /o/, and u is /u/; they are not pronounced /aɪ/, /oʊ/, or /juː/.

Each letter is pronounced independently. There are no silent letters, digraphs, or context-dependent pronunciations.

Words are divided into syllables at each consonant–vowel pair and stress falls on the first syllable.

For example:

Word<br>IPA

sibo<br>/ˈsi.bo/

katu<br>/ˈka.tu/

pova<br>/ˈpo.va/

Minor accent-dependent differences in pronunciation are acceptable as long as the encoded letters remain distinguishable.

Algorithm

Treat the input as a bit stream and split it into 6-bit chunks, most<br>significant bit first. Each chunk maps directly to one syllable:

bits 5..2 → consonant index 0..15<br>bits 1..0 → vowel index 0..3

For L input bytes, emit n = ceil(8·L / 6) syllables. If the final<br>chunk has fewer than six input bits, zero-fill its low bits. These<br>zeroes are canonical padding and carry no information.

A complete encoding is self-sizing: L = floor(6·n / 8). The decoder<br>reconstructs the 6-bit chunks, infers L, returns the first 8·L bits,<br>and MUST reject non-canonical syllable counts or non-zero padding.<br>Leading zero bytes are preserved.

This applies to complete encodings . A truncated prefix does not<br>indicate whether more syllables follow.

A prefix of k syllables commits to the first 6·k bits of the encoded<br>value and is verified by recomputation, not decoding.

Variants

A variant is an alternative reversible representation of the same byte<br>string. The variant identifier is encoded in the representation, so<br>decoding requires no external metadata.

For input X and variant v = 0…15:

M(0, n) = 0^n<br>M(v, n) = SHAKE-256("sing-song/variant" ‖ byte(v), n) for v > 0<br>Y = X XOR M(v, len(X))

Encode Y with the ordinary Sing-song codec. Because XOR is<br>self-inverse:

X = Y XOR M(v, len(Y))

The mask is public and provides no confidentiality. SHAKE-256 produces a<br>deterministic stream, preserving the prefix-stability property described<br>above. Variant 0 is the direct encoding.

The variant identifier is rendered as a trailing two-letter suffix: one<br>vowel followed by one of l m n r:

v = 4·i + j where vowel = "aiou"[i], consonant = "lmnr"[j]

0=al 1=am 2=an 3=ar 4=il 5=im 6=in 7=ir<br>8=ol 9=om 10=on 11=or 12=ul 13=um 14=un 15=ur

Variant 0 SHOULD be rendered without a suffix; parsers MUST accept an<br>explicit al as equivalent.

Parity disambiguates...

sing song syllables encoding variant syllable

Related Articles