{"id":37227495,"url":"https://github.com/hurui200320/utf8-ctc","last_synced_at":"2026-01-15T03:22:12.166Z","repository":{"id":231890401,"uuid":"782965186","full_name":"hurui200320/utf8-ctc","owner":"hurui200320","description":"Chinese telegraph code, but use UTF8 as fallback.","archived":false,"fork":false,"pushed_at":"2026-01-10T17:41:03.000Z","size":158,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"master","last_synced_at":"2026-01-11T03:48:08.522Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Kotlin","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"agpl-3.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/hurui200320.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2024-04-06T14:55:34.000Z","updated_at":"2026-01-10T17:40:42.000Z","dependencies_parsed_at":"2026-01-11T01:01:59.712Z","dependency_job_id":null,"html_url":"https://github.com/hurui200320/utf8-ctc","commit_stats":null,"previous_names":["hurui200320/utf8-ctc"],"tags_count":8,"template":false,"template_full_name":null,"purl":"pkg:github/hurui200320/utf8-ctc","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hurui200320%2Futf8-ctc","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hurui200320%2Futf8-ctc/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hurui200320%2Futf8-ctc/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hurui200320%2Futf8-ctc/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/hurui200320","download_url":"https://codeload.github.com/hurui200320/utf8-ctc/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hurui200320%2Futf8-ctc/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28442268,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-01-15T00:55:22.719Z","status":"online","status_checked_at":"2026-01-15T02:00:08.019Z","response_time":62,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2026-01-15T03:22:10.490Z","updated_at":"2026-01-15T03:22:12.161Z","avatar_url":"https://github.com/hurui200320.png","language":"Kotlin","funding_links":[],"categories":[],"sub_categories":[],"readme":"# utf8-ctc\nChinese telegraph code, but use UTF8 as a fallback.\n\n[简体中文说明](./readme_zh-CN.md)\n\n## What is CTC? And why use it in 20XX?\n\nCTC is the shorthand for \"Chinese Telegraph Code\".\nIt compiles most of the common characters and assigns them a number.\nFor example, character `汉` is numbered `3352`.\nThis is a more compact way to index Chinese:\nIt only uses two bytes (actually it's only 0000 to 9999),\nwhile UTF-8 uses three bytes on average.\n\nWhile UTF-8 is generally the best option to handle all kinds of characters,\nwhen talking about encoding along with a limitation on length,\nCTC becomes useful.\n\n## What is this program for?\n\nThis program is written for encoding text on postcards, while we don't want to\ndeal with encrypted data represented in base58, but still want some level of privacy.\nSo this program encodes the Chinese into CTC, and if there is a missing character,\nit uses either raw UTF-8 or compressed UTF-8 to encode.\n\n\u003e Handwriting and typing numbers are much easier than base64/58.\n\nThe design is: when writing postcards, I encode the text either from cli options,\nor files, or from `stdin`, then it spills out a bunch of numbers, and I just need\nto write them on the postcard.\n\nWhen someone got the postcard, he can type in the numbers and the program will\nprint out the decoded message.\n\n## Usage\n\nThe program is built using jlink with zulu 21 jdk, so technically you don't need\na Java runtime installed on your pc.\nDownload the correct build for your usage and invoke `./ctc`, everything should be fine.\n\n\u003e There is no package published to use this codec as a dependency.\n\u003e I didn't write to dependency, I didn't test, so I don't want to people use it\n\u003e and accidentally cause some disaster.\n\u003e You can try with the jitpack, but I won't ensure the result.\n\u003e \n\u003e ***If this demand is popular, create an issue and I will work on it to publish as a dependency***\n\n### Encoding\n\nYou can encode text from the cli option, file, and stdin.\n\n```bash\n./ctc encode -t \"天匠染青红，花腰呈袅娜。\"\n./ctc encode -f message.txt\necho \"天匠染青红，花腰呈袅娜。\" | ./ctc encode -c UTF-8\n```\n\nThe `-t \u003ctext\u003e` option will omit the `-f \u003cfile\u003e` if they are both specified.\nWhen using the stdin, you need to manually tell the program you're done by inputting\n`EOF` on a new line.\n\nYou can change the `EOF` to something else using `--eof=EOT`, now you can use `EOT`\ninstead of `EOF`.\n\nYou can also change how many codes are printed in one line.\nBut do be aware this is limited by your terminal width, if it's longer than the width, it will wrap.\nBy default, it's fit your terminal.\nYou can change it by option `-w 6`, now you have six codes per line.\n\nWhen using stdin input, there is some issue with the charset on Windows.\nBy default, the program uses UTF-8 to read and write everything.\nBut on windows, it will use `GBK` if the default locale is `zh-CN`;\nor use `BIG5` if the default locale is `zh-TW`.\nIf you don't want this feature, you can use `-c UTF-8` to force the program to\nuse UTC-8 charset.\n\nDo verify the program output before you write numbers to your postcard.\nSometimes the charset issue can mess you up if you don't check the decoded result.\n\n### Decoding\n\nIt's basically the same, but much simpler.\nWhen decoding, the program will print everything using UTF-8,\nwhich most terminals are ok, even on windows.\n\nFor decoding, there are only three options: `-t`, `-f` and `--eof`.\n\nYou can type any character, and the program will ignore them and only take the digits.\nSo don't worry if you accidentally typed a letter or something.\nKeep typing numbers and you're good.\n\n```bash\n./ctc decode -t \"1131  0561  2676  7230  4767  9976  5363  5212  0701  5934  1226  9975   84\"\n```\n\n### Encryption\n\nStarting from v1.0.0, I removed the old transposition cipher because it's not safe.\nInstead, I added ChaCha20 stream cipher for encryption.\n\nThe ChaCha20 stream cipher will generate a stream of fake codes ranged from 0000 to 9999 (key).\nThen for each encoded CTC code, we calculate the encrypted code:\n```\nenc = (code + key) % 10000\n```\n\nWhen decrypting, the same stream of fake codes will be generated using the same key and nonce:\n```\ncode = (enc - key + 10000) % 10000\n```\n\nThe nonce will be generated at the encrypting time,\nand is required via cli option `--nonce` (`-n` for short) during the decrypting time.\n\nThe key (`-k` or `--key`) will be decoded differently depending on the encryption mode.\n\nIf you use symmetric encryption, the key will be decoded as UTF-8 bytes and apply SH3-256.\nThe result will be the ChaCha20 stream key.\n\nIf you use asymmetric encryption, the key will be decoded as hex string to be private key,\nthen the `--dh hex` option will be used to as your partner's public key (also as hex string).\nThen use X25519 ECDH to generate the shared secret, and then apply SHA3-256.\nThe result will be the ChaCha20 stream key.\n\nFor asymmetric encryption, to generate the private key, use `openssl rand -hex 32`.\nTo get the public key, use `./ctc pubkey \u003cyour private key in hex\u003e` to calculate the public key.\n\nWhen encryption is enabled, the program will also generate an MAC to ensure the integrity of the message.\nThis will be generated on encrypting time, and will be required on decrypting time via `--mac hex` (`-m` for short).\n\n## Internal design\n\n### Preprocess\n\nThere is some internal processing beyond simply lookup the table and do the substitution.\nThe CTC is scraped from https://en.wiktionary.org/wiki/Appendix:Chinese_telegraph_code/Mainland_1983.\n\nBefore starting encoding characters, we need to replace some text for shorter codes:\n+ new lines (`\\n`) are replaced by `〷` (code 9999)\n+ text like `10日` will be replaced by the char `㏩` (code 9910)\n\nThis will save some code and will be transparent for user.\nWhen decoding, reversed processing will be applied to make sure the decoded\ntext is looking normal.\n\n### UTF-8 fallback\n\nWhen there is an unknown character, it will save to the buffer and encode them in batches.\nFor example, when encoding `大家好，my name is XXX。`, the unknown buffer will be `my name is XXX`,\nthen it will be encoded to utf-8 bytes.\nThe encoded bytes will be compressed by LZMA2 with preset max and dict size of 256KB,\nand the result will be kept if the compress result is shorter than the raw form.\n\nFor raw UTF-8 bytes, it will be enclosed with `9992` and `9993`, the content\nwill be representing in 0000 to 9991, like base9992 but all in numbers.\n\nFor compressed UTF-8 bytes, it will be enclosed with `9994` and `9995`.\nThe content representation is the same.\n\n## Checksum\n\nTo ensure the integrity of the encoded data and also to ensure the typing is correct,\nI added a checksum at the end of each encoded line.\n\nFor example, the text `天匠染青红，花腰呈袅娜。` corresponding to the following code:\n\n```\n1131  0561  2676  7230\n4767  9976  5363  5212\n0701  5934  1226  9975\n```\n\nWhen printing out each line, the ISO 7064 mod 97–10 checksum will be appended to the end.\nSo the actual output will be (use `-w 4` to specify 4 codes per line):\n\n```\n1131  0561  2676  7230   17\n4767  9976  5363  5212   92\n0701  5934  1226  9975   62\n```\n\n***When decoding, the checksum is always REQUIRED.*** If you don't know/have the checksum,\nor the checksum is blurred and is indistinguishable, just use `00` (must be two digits).\nAlso, the line break is also required since the decoding process will check each line separately.\nSo you can't mix two lines into one. You have to type them as-is (blank chars are ok, they will be ignored).\n\n## Contributes\n\nWelcome, but I can't guarantee if I accept the pr or not.\nOpen issues as long as you have questions, but I can't guarantee to answer them.\n\nTL;DR: I give no guarantee on the program, unless you pay me.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fhurui200320%2Futf8-ctc","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fhurui200320%2Futf8-ctc","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fhurui200320%2Futf8-ctc/lists"}