Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,8 @@
- 可靠,代码经过严格单元测试。
- 便捷,易于本地部署和使用。

> 原创逆向研究,特别支持解密熊曰(与熊论道)密文。
---

### **熔古铸今:文言文仿真加密**
Expand Down
27 changes: 27 additions & 0 deletions docs/document/js-deploy.md
Original file line number Diff line number Diff line change
Expand Up @@ -245,6 +245,33 @@ Abra.OldInput(input, mode, key, q);

在无错误的情况下, `OldInput()` 函数的返回值通常是 `0`。

### BearDecode() 熊曰解密函数

::: warning 致敬

在此致敬算法原开发者坑晨,以及萌研社。

:::

`BearDecode()` 允许用户解密熊曰密文。

```js
import { Abracadabra } from "abracadabra-cn";

let Abra = new Abracadabra(); //不附带参数。

//只允许输入字符串(UTF-8)
Abra.BearDecode(
"呋擊眠魚堅笨唬咬呱洞物沒呦山誒註歡動笨意非覺呆誘嘿吖盜噗嗥溫沒洞魚啽和現現很哞呦蜜呱和出偶人嗷誒訴偶冬果果很森喜嗅噤很覺家森類雜拙呆意雜常吃"
);

let Result = Abra.Output(); //获取输出,输出只会是字符串
```

熊曰密文之解密,是本项目的原创逆向研究,基于对熊曰密文的已知明文攻击。

适用于萌研社与熊论道(熊曰加密)2020 年算法更新后的密文。

### Output()

```js
Expand Down
2 changes: 2 additions & 0 deletions docs/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,8 @@ Abracadabra(魔曰) 是开源,安全,高效的文本加密工具。
- 可靠,代码经过严格单元测试。
- 便捷,易于本地部署和使用。

> 原创逆向研究,特别支持解密熊曰(与熊论道)密文。
### **熔古铸今:文言文仿真加密**

> 早夏振于局而听恋,路在临驿,静星之舒,迸于夏。梦曰:“不请流也” ,星雅即灯明,雪近即城极,返林而不能放,开而不能指,镜也。
Expand Down
4 changes: 2 additions & 2 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
"name": "abracadabra-cn",
"description": "Use Chinese to Encode Everything",
"private": false,
"version": "3.3.1",
"version": "3.3.3",
"main": "./dist/abracadabra-cn.js",
"types": "./dist/abracadabra-cn.d.ts",
"type": "module",
Expand Down
178 changes: 178 additions & 0 deletions src/javascript/XiongyueDecHelper.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,178 @@
/*
* Copyright (C) 2026 SheepChef (a.k.a. Haruka Hokuto)
*
* 这是一个自由软件。
* 在遵守AIPL-1.1许可证的前提下,
* 你可以自由复制,修改,分发,使用它。
*
* 查阅 Academic Innovation Protection License(AIPL) 来了解更多 .
* 本作品应随附一份完整的 AIPL-1.1 许可证全文。
*
*/

/*
* ACKNOWLEDGEMENT
*
* Copyright (C) 2020 PcMoe(坑晨)
*
* 在此致敬萌研社,以及其开发者坑晨。
* 请勿将本开源档案用作商用,以及任何非法用途
*
*/

// 透过已知明文攻击得出的字典
// 注意这个词典是顺序有关的,禁止修改顺序。

import pako from "pako";

const xiongyueDict = [
"食",
"性",
"很",
"雜",
"既",
"溫",
"和",
"會",
"誘",
"捕",
"動",
"物",
"家",
"住",
"山",
"洞",
"沒",
"有",
"冬",
"眠",
"偶",
"爾",
"襲",
"擊",
"人",
"類",
"呱",
"哞",
"嗄",
"哈",
"嘍",
"啽",
"唬",
"咯",
"呦",
"嗷",
"嗡",
"哮",
"嗥",
"嗒",
"嗚",
"吖",
"吃",
"嗅",
"嘶",
"噔",
"咬",
"噗",
"嘿",
"嚁",
"噤",
"囑",
"非",
"常",
"喜",
"歡",
"堅",
"果",
"魚",
"肉",
"蜂",
"蜜",
"註",
"取",
"象",
"發",
"達",
"你",
"覺",
"出",
"更",
"盜",
"森",
"氏",
"我",
"誒",
"怎",
"寶",
"麼",
"圖",
"現",
"破",
"嚄",
"告",
"訴",
"樣",
"呆",
"萌",
"笨",
"拙",
"意",
];

const reverseDict = new Map();
xiongyueDict.forEach((char, idx) => reverseDict.set(char, idx));

// Base91 解码函数
function base91DecodeValues(vals) {
let b = 0,
n = 0,
v = -1;
const out = [];

for (let i = 0; i < vals.length; i++) {
let val = vals[i];
if (v < 0) {
v = val;
} else {
v += val * 91;
b |= v << n;
n += (v & 8191) > 88 ? 13 : 14;
do {
out.push(b & 255);
b >>= 8;
n -= 8;
} while (n > 7);
v = -1;
}
}
if (v + 1) {
out.push((b | (v << n)) & 255);
}
return new Uint8Array(out);
}

//解密主函数
export function decryptXiongyueSync(ciphertext) {
// 去标头并倒序
const chars = Array.from(ciphertext.substring(1)).reverse();

// 查字典恢复 Base91 数值
const b91Vals = chars.map((char) => {
if (!reverseDict.has(char)) throw new Error(`非法的熊曰密文字符: ${char}`);
return reverseDict.get(char);
});

// Base91 解码成二进制流
const deflatedBytes = base91DecodeValues(b91Vals);

try {
// Deflate 解压
const ptBytes = pako.inflateRaw(deflatedBytes);

// UTF-8 解码
const textDecoder = new TextDecoder("utf-8");
return textDecoder.decode(ptBytes);
} catch (err) {
throw new Error("损坏的熊曰密文");
}
}
11 changes: 11 additions & 0 deletions src/javascript/main.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,17 @@ export class Abracadabra {
l?: boolean
): number;

/**
* 魔曰 解密熊曰加密密文
*
* @param {string} input 输入的数据,只能是字符串
* @return {number} 成功则返回 0(失败不会返回,会抛出异常)
*
* 解密与熊论道(熊曰加密)2020年算法更新后的密文。
*
*/
BearDecode(input: string): number;

/**
* 魔曰 获取加密/解密后的结果
* @returns {string | Uint8Array} 根据此前指定的输出类型,可能是字符串或字节数组
Expand Down
15 changes: 15 additions & 0 deletions src/javascript/main.js
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
import * as Core from "./CoreHandler.js";
import { preCheck_OLD, PreCheckResult, stringToUint8Array } from "./Misc.js";
import { AdvancedEncConfig } from "./CoreHandler.js";
import { decryptXiongyueSync } from "./XiongyueDecHelper.js";
export class Abracadabra {
//主类

Expand Down Expand Up @@ -202,6 +203,20 @@ export class Abracadabra {
return 0;
}

/**
* 魔曰 解密熊曰加密密文
*
* @param{string}input 输入的数据,只能是字符串
*
* 解密与熊论道(熊曰加密)2020年算法更新后的密文。
*
*/

BearDecode(input) {
this.#res = { output: decryptXiongyueSync(input) };
return 0;
}

/**
* 魔曰 获取加密/解密后的结果
*/
Expand Down
17 changes: 17 additions & 0 deletions src/javascript/main.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,23 @@ test("加/解密测试", { timeout: 15000 }, () => {
TestTemp3 = Abra.Output();

expect(TestTemp3).toBe(TestString);

const XiongyueWord =
"呋擊眠魚堅笨唬咬呱洞物沒呦山誒註歡動笨意非覺呆誘嘿吖盜噗嗥溫沒洞魚啽和現現很哞呦蜜呱和出偶人嗷誒訴偶冬果果很森喜嗅噤很覺家森類雜拙呆意雜常吃";
const ExpectedXiongyueWordDecRes = "我能看见,有些东西就在遥远的另一边";

Abra.BearDecode(XiongyueWord);
TestTemp3 = Abra.Output();
expect(TestTemp3).toBe(ExpectedXiongyueWordDecRes);

const XiongyueWord2 =
"呋食你噔你囑吃有現蜂擊常出嗄嗄雜和捕氏囑嚄樣誘哈肉嘍誘嚄有嚁告嗅嗚嘶覺眠麼眠類住蜜誘家嗚嚁和冬萌會我呆嗅歡堅嗚歡吖很唬啽達笨會訴嘍嗚動喜樣囑歡嗥啽性沒擊歡住怎類取笨達嗚嗥喜森住捕嗡山蜜擊嗡嗥家啽冬嗅達蜂嗄怎你咬山眠冬會啽類偶偶告吖捕森呦註你現魚洞達破嘿哈噗蜜捕哮破呱寶嗷和發咯喜嚁堅達我萌噔樣哞我哈住嚄類家爾現家誘哈爾既嗄發取嘶出蜜圖盜喜嘶住既達誘註和歡有唬註襲爾捕喜嗒盜和嘍肉冬山會果既麼哞住沒哈氏達住更雜嗥註取盜哞萌訴意告噔嗡嘿嚄咯囑嗥物雜歡很哞怎嗄住偶嘶襲住會吖眠雜樣出森囑沒取爾意誒溫爾蜜麼性爾嗄爾覺噔嗥有嗥常物噔哞囑人既冬嗥咯破堅呦捕溫既氏歡噔啽森誒嘍肉嘶萌嚁啽咯吃呆很吖很吃更溫喜眠發吃嗷覺物森擊麼蜜破家有訴堅你哮囑覺森更嗄溫拙誘你沒拙圖嗥眠樣發寶喜告取破拙嗷怎誒果註肉呱很怎嚄拙怎萌歡人盜更註食嗥性發堅告噗洞咬蜂破爾常嚄怎咬性象拙嘶住吃註達啽嘿眠咬山嗅發囑很蜜森非常嚁取你動嗚偶嘶萌物嗷常捕嘶蜜常噤唬誘吖誘出意物果人怎蜜襲嗚動堅達訴麼我和哈冬蜜麼果物很你家哈樣食洞人嘍魚意噗盜果吖現吃類哞山性拙發會更擊象捕出類歡象哞現果樣性寶蜜襲山覺呆和沒盜咯我洞萌喜破會達沒嘍取很寶意蜜哞吖嗡更噔呱食噗噗爾唬動我笨拙嗡註嚄象噗嗥咬吃嘍吃擊和山覺發樣會哈擊怎咬囑嘶笨告嗚食意更囑偶哈冬山哈蜜呆哞和噗拙爾告食很哈嗡家噔覺發麼會現眠達呱告爾達歡會吃更笨誘既物眠很常意寶果物捕嗡呦你噤萌森人寶覺咯圖常襲非很噗嗷你很圖達有家有偶既嗥我哞擊咯吃類誘氏喜嗅覺有蜜偶既吖山現嘍噗咬沒肉意麼噤嗚吖啽人會嗚發嘿發會笨更嚄喜住眠咯歡捕氏啽嚁我物堅哈噔嗡誒嘍魚誒訴住嗅有動哞哮嘶會家怎嚄象和噔常哮誘達笨我誘偶取哈會你圖告常咯洞冬和嗡擊嚄雜我性盜洞歡噗嗒達圖捕意註吖萌捕和嘍嗅嘶物擊雜物家嚄拙嗄哈動吖破冬覺唬哈和歡冬沒你嗚樣肉森笨怎取取意嗥唬意有家圖嘍魚囑森嗄吃會人現噤象和人寶盜破非圖破吖非嘿現嗡蜂哮萌森笨沒麼眠盜吃笨蜜噤哮擊哞哈嚁人冬會啽洞嘶人寶哮嗅嘶咯出噔笨咬喜嗄偶哮咬呱雜類魚非既象嘶哮嗥哮嘿圖嘿笨樣象襲笨呦破盜嗡眠告嘍歡達住取歡破吃現蜂爾溫冬覺象嗚誒嘍住萌破拙物堅我意捕達呱麼沒噗嚁達性嗥物會覺嗷物咯哞麼吃達既會非呦嗅既蜂沒沒盜啽象出堅盜嗒嗚怎誘我家怎動啽出山象吖怎捕萌萌蜂吖噤寶盜會你噤嗥笨意嚄溫類肉雜盜噗現咯出唬嗚物有既註冬擊動吖山你嘶盜擊魚很象性噔嗅嗷類發嘍既眠家取喜嗄雜噔啽冬我啽會果爾呱意樣怎沒哞偶呆更嚁笨啽嗥你物歡爾果現山動肉山蜂咬森非註萌哮吃襲寶象爾常哮肉嗷沒哈非嗒會嚄唬咯果爾象眠嗷洞咯盜眠註雜唬象現性森嗥山我爾出呦洞萌噤拙咬肉既眠沒嚁嗒爾嚁萌噤唬嗚動襲堅家山啽噤告人嘿告訴樣果眠啽類魚噗萌物覺果嘿盜蜂蜜常咬和類常擊蜂歡嚄常笨現嗥出你笨既家取呆嘿圖捕噔嗄我誒眠噔象嗡盜囑嚄訴果動唬訴呦嘍住很萌既嗒呆呱嘿麼捕拙嗒告肉達嗚沒怎覺哞既笨堅咯出圖嗷嘍圖哞肉嚁住哈既冬咯物嗄氏嗄吃哈唬溫襲爾魚非堅呦咯達麼呦哞嗡洞嚄嗡有眠嘶破沒果家咯噤溫寶雜會動冬我森囑哈現哈嗥沒咯圖有嗷山更擊現盜魚喜喜沒嚄圖雜更訴盜呦嗚動呦嗚氏註動嘶沒更蜜沒喜吃我取冬魚吖圖會溫噤嘍住類哈嘿溫噗果常呦動嗥笨性呦物破動意嗚捕嗥溫誘嘿嗚捕告拙噤我肉氏嚁家樣肉類很哮訴嗡現象呱家啽嗡覺註動嘶噔象告嗚魚既爾人森啽哞堅嗥覺會喜擊咬物爾動人覺嗚告哮捕果常盜食告嗚吖非人噗誒氏嘍襲氏嗡嘶氏寶捕麼嗥蜂呆家動嗡拙魚呆哞嚄噤萌會住物住嘿寶山告嗅洞發爾訴盜嗒告嘿盜哮呆嗡呦歡寶冬嗒訴堅嗚哞囑覺偶嗚沒爾破非偶會笨嚄唬麼誒覺嘍象嚄歡會寶呆哞嗡哞眠現溫物發怎既眠住訴魚怎囑出咯發象森和噤很動有性襲魚嘍洞和和山動物呦常咬和嗡笨覺嗅呆你食性魚出山象呱取誘";
const ExpectedXiongyueWordDecRes2 =
"\n诶..朋友们好啊,我是混元形意太极门掌门人——马保国刚才有个朋友问我马老师发生什么事了,我说怎么回事,给我发了几张截图。我一看!嗷!原来是昨天,有两个年轻人。三十多岁,一个体重,九十多公斤,一个体重八十多公斤。他们说,诶...有一个说是我在健身房练功颈椎练坏了,马老师你能不能教教我浑元功法,诶...帮助治疗一下,我的颈椎病。我说可以。我说你在健身房练死劲儿,不好用,他不服气。诶...我说小朋友,你两个手来折我一个手指头,他折不动。他说你这也没用。我说我这个有用,这是化劲儿,传统功夫是讲化劲儿的,四两拨千金。二百多斤的英国大力士,都握不动我这一个手指头啊…哈!他非要和我试试,我说可以。诶…我一说完他啪就站起来了,很快啊!然后上来就是一个左正蹬,吭,一个右鞭腿一个左刺拳,我全部防区(口误)防出去了啊!防出去以后自然是传统功夫以点到为止,右拳放到他鼻子上没打他,我笑一下准备收拳,因为这时间,按传统功夫的点到为止他已经输了。如果这一拳发力,一拳就把他鼻子打骨折了,放在鼻子上没有打他,他也承认,我先打到他面部。他不知道拳放在他鼻子上,他承认我先打到他面部,啊!我收拳的时间不打了,他突然袭击,左刺拳来打我脸,啊,我大意了啊,没有闪,诶…他的左拳给我眼,啊,右眼,蹭了一下,但没关系啊!他也说,啊他截图也说了,两分多钟以后,当时流眼泪了,捂着眼,我说停停。然后两分钟...钟以后,两分多钟以后诶就好啦,我说小伙子你不讲武德你不懂,我说马老师对不...对不起,我不懂规矩。啊,我是…他说他是乱打的,他可不是乱打的啊,正蹬鞭腿左刺拳,训练有素,后来他说他练过三四年泰拳。啊,看来是,有备而来!这两个年轻人不讲武德,来骗!来偷袭,我六十九岁的老同志。这好吗?这不好!我劝!这位年轻人好自为之,好好反思,以后不要再犯这样的聪明,小聪明,啊,呃…武林要以和为贵,要讲武德,不要搞窝里斗。谢谢朋友们!";

Abra.BearDecode(XiongyueWord2);
TestTemp3 = Abra.Output();
expect(TestTemp3).toBe(ExpectedXiongyueWordDecRes2);
});

test("链接压缩测试", { timeout: 15000 }, () => {
Expand Down