diff options
| author | mayx <mayx@outlook.com> | 2026-10-07 08:16:54 +0200 |
|---|---|---|
| committer | mayx <mayx@outlook.com> | 2026-10-07 08:16:54 +0200 |
| commit | 7f6baa0c8d5d51a20bfec7867a88f381bf99ab6a (patch) | |
| tree | 43d8798948c3f3fc78416de0d1bb796e1eb6942a /_posts | |
| parent | 1052b66270cb9ed7b5f3760a50a909ecc7f33669 (diff) | |
- /_tools/serv00_post-receive
- /_posts/2026-10-01-quine.md
Diffstat (limited to '_posts')
| -rw-r--r-- | _posts/2026-10-01-quine.md | 562 |
1 files changed, 562 insertions, 0 deletions
diff --git a/_posts/2026-10-01-quine.md b/_posts/2026-10-01-quine.md index 237eed8..bef3437 100644 --- a/_posts/2026-10-01-quine.md +++ b/_posts/2026-10-01-quine.md @@ -190,6 +190,568 @@ class BlogQuine: 于是我第一时间就把原来的TGZ压缩命令换掉,换成了AI给我写的[blogquine.py](https://github.com/Mabbs/mabbs.github.io/blob/master/_tools/blogquine.py),现在就可以通过[这里](https://mayx.eu.org/MayxBlog.7z)下载到“完整”包含我博客所有内容的压缩包了。 不过唯一的问题就是这样做出来的压缩包并没有压缩😂,相当于给做成了普通的归档了。当然我的博客本身倒是不大,没压缩也多不了多少空间,但相比于能做出“完整”的效果来说,这点浪费的空间也是小问题了。 +## 基于博客压缩包的离线模式(2026.10.03更新) + 既然现在的AI什么都能做了,那上次我因为技术不足仅仅只是用[Service Worker做了个代理](/2025/08/01/sw-proxy.html),现在也可以升级成下载全站之后让全站离线的功能吧?不过之前做的压缩包并没有压缩,导致整个压缩包有接近20MiB的大小,后来我仔细想了一下我的需求,我只是想让下载全站压缩包的按钮不断链,并没有说解压后的文件一定就必须是它本身,所以我只要用相同的文件名再压缩一次应该就可以了,这样既能满足我的想法,又可以让其他人下载的时候不会花费太多的时间。 + 在我直接压缩之后,整个压缩包占用大概9MiB的空间,其实我已经很满意了,不过压之前是18MiB,也就是说压缩率是50%……虽然也不是不能接受,但我在想这是不是合理的结果呢?我让AI分析了一下50%的压缩率正不正常,它看了一眼之后告诉我文本部分的10MiB压缩完之后有1MiB,图片因为压不动所以直接占用了8MiB😅,这时候我才意识到原来我一直存着一堆占着大量空间的垃圾,而且还是用的PNG/JPG这种压缩率很低的格式……考虑到兼容性和压缩效果,我把占用比较大的图片转换为了WebP格式,最终整个压缩包就只占用了4MiB的空间,一口气又节省了50%的空间。 + 最后做完对压缩包的处理之后,我直接让AI给我基于那个压缩包制作离线模式,它轻轻松松就[做出来](https://mayx.eu.org/offline.html)了,最终使用的是[libarchive库](https://github.com/nika-begiashvili/libarchivejs),在启用离线模式之后整个网站的速度简直就是0延迟,点击就能瞬间跳转,效果算是相当不错了。 +## 受大佬启发制作了能压缩的7z Quine(2026.10.05更新) + 做完博客压缩包之后我突发奇想,虽然东西是AI做的,但也是在我的手中做出了世界上第一个LZMA2 Quine,那么如果我向全世界第一个制作ZIP Quine的人展示一下我的作品会怎么样呢?目前可以知道,世界上第一个制作ZIP Quine的人是[Erling Ellingsen](https://infosec.exchange/@steike),所以我向他发了个帖子[展示了一下](https://infosec.exchange/@mayx/117385801954308033)。大佬不愧是大佬,一眼就能看出理论上能压缩的7z Quine是可以做出来的,对我来说,我是完全不知道7-Zip居然还支持链式编解码,能可以通过“double lzma2”的方式做到既可以自包含、又能真正被压缩的压缩包。既然大佬说理论上可以,那我自然是相信的,于是就让AI给我使劲折腾想办法把它做出来。在折腾了一晚上之后AI终于做出来了,真是强得可怕: +```python +# ============================================================ +# 双层 LZMA2 的 7z quine("double lzma2") +# +# F = S32 ‖ P ‖ H,folder 的 coder 链 = [LZMA2(外层), LZMA2(内层)], +# 解码管线:P --外层--> I --内层--> U。 +# +# I = Cseg ‖ LBseg ‖ Mseg ‖ 0x00 +# Cseg : 真实 LZMA2 对 content 的压缩流(内容真正的压缩数据 C) +# LBseg: 内层 store 链,载荷 = seed(seed 内含一份 C 的参照副本) +# Mseg : 内层 match 链,输出 quine 区(= F 的逐字节副本) +# U = content ‖ seed ‖ F +# +# 外层把 I 再压一遍:Cseg 用 store 链原样承载;seed 里的 C 参照副本与 Cseg +# 逐字节相同,被外层的 rep0 回溯匹配消掉,于是成品里只剩一份压缩数据。 +# quine 区回引 P 的字节时,源全在 seed 里(C 副本 / 头样本表 / 机械串)。 +# ============================================================ +def lzma_chunk(tokens, out_pos): + """编一个 LZMA chunk(0xC0: state+props reset,无 dict reset,无 end marker)。 + match token 的编码字节只取决于 (dist,len,pos),与历史内容无关(不维护输出历史)。 + 解压长度用 21 位(控制字节低 5 位存高 5 位),故单 chunk 输出上限 2 MiB。""" + enc = LzmaEncoder() + enc.pos = out_pos + total = 0 + for t in tokens: + if t[0] == "m": + enc.match(t[1], t[2]) + total += t[2] + else: + enc.rep_match(t[1]) + total += t[1] + data = enc.finish() + u = total - 1 + c = len(data) - 1 + assert 0 <= u < (1 << 21) and 0 <= c < 65536, (total, len(data)) + hdr = bytes([0xC0 | ((u >> 16) & 0x1F)]) + (u & 0xFFFF).to_bytes(2, "big") + \ + (c & 0xFFFF).to_bytes(2, "big") + bytes([PROPS_BYTE]) + return hdr + data, total + +LZ2_MAXU = 1 << 21 # LZMA2 单个 LZMA chunk 的解压上限 + + +def lzma2_raw(data, dict_size, preset=6): + """FORMAT_RAW + LZMA2 压缩;去掉结尾 0x00 便于后面继续追加 chunk。""" + c = lzma.LZMACompressor( + format=lzma.FORMAT_RAW, + filters=[{"id": lzma.FILTER_LZMA2, "dict_size": dict_size, "preset": preset}]) + out = c.compress(data) + c.flush() + assert out and out[-1] == 0x00, "LZMA2 流应以 0x00 结尾" + return out[:-1] + + +def split_len(n, cap): + """按 cap 上限切分 n 字节。末片若为 1 字节则从前一片借 1(match 最短为 2)。""" + Ls, rem = [], n + while rem > cap: + Ls.append(cap) + rem -= cap + if rem == 1 and Ls: + Ls[-1] -= 1 + rem = 2 + Ls.append(rem) + return Ls + + +class DoubleQuine(BlogQuine): + """双层 LZMA2 版本:folder = [LZMA2(外层), LZMA2(内层)]。""" + + def entries(self): + """U 的顺序是 内容文件… ‖ seed ‖ quine,条目顺序必须与之对应。""" + ent = [{"name": r, "dir": isd} for r, isd in self.walk_entries] + ent.append({"name": self.seed_name, "dir": False}) + ent.append({"name": self.quine_name, "dir": False}) + return ent + + # ---------- 头部:双 coder + BindPair ---------- + def build_header(self, n, total, d, entries, sub_sizes, size_I): + n_sub = len(sub_sizes) + N = len(entries) + h = bytearray() + h += b"\x01\x04" # kHeader, kMainStreamsInfo + h += b"\x06" + varint(0) + varint(1) + b"\x09" + varint(n) + b"\x00" + h += b"\x07" # kUnpackInfo + h += b"\x0b" + varint(1) + b"\x00" # kFolder: 1, local + h += varint(2) # NumCoders = 2 + h += b"\x21\x21" + varint(1) + bytes([self.dict_prop_out]) # coder0 = 外层 + h += b"\x21\x21" + varint(1) + bytes([self.dict_prop_in]) # coder1 = 内层 + h += varint(1) + varint(0) # BindPair = (InIndex=1, OutIndex=0) + h += b"\x0c" + varint(size_I) + varint(d + total) # 两个 coder 的输出大小 + h += b"\x00" + h += b"\x08" # SubStreamsInfo + h += b"\x0d" + varint(n_sub) + h += b"\x09" + b"".join(varint(s) for s in sub_sizes[:-1]) + h += b"\x0a" + b"\x01" + crc_base = len(h) + h += b"\x00" * (4 * n_sub) + h += b"\x00\x00" + h += b"\x05" + varint(N) # FilesInfo + bits = bytearray((N + 7) // 8) + for i, e in enumerate(entries): + if e["dir"]: + bits[i // 8] |= 1 << (7 - i % 8) + h += b"\x0e" + varint(len(bits)) + bytes(bits) + mt = b"\x01\x00" + struct.pack("<Q", self.mtime_ft) * N + h += b"\x14" + varint(len(mt)) + mt + names = bytearray(b"\x00") + for e in entries: + names += e["name"].encode("utf-16-le") + b"\x00\x00" + h += b"\x11" + varint(len(names)) + bytes(names) + attrs = b"".join(struct.pack("<I", 0x10 if e["dir"] else 0x20) + for e in entries) + h += b"\x15" + varint(2 + len(attrs)) + b"\x01\x00" + attrs + h += b"\x00\x00" + return bytes(h), crc_base + + # ---------- 布局:三层坐标的不动点迭代 ---------- + def layout(self): + content = self.content + dc = len(content) + dict_c = max(1 << 20, 1 << max(20, dc.bit_length())) + C = lzma2_raw(content, dict_c) + self._C = C # 内容压缩只做一次,finalize 复用 + lc = len(C) + # 迭代变量:Y = plant 长度, H = 头部长度, M = Mseg 字节数 + Y, H, M = 96, 256, 256 + seen = set() + for _ in range(200): + ds = lc + 32 + H + Y # seed = C副本‖S32‖H‖plant + d = dc + ds + Ls_LB = split_len(ds, CHUNK) + lLB = 3 * len(Ls_LB) + ds + off_in = lc + lLB + M1 = M + 1 # Mseg ‖ 内层流终止符 0x00 + Ls_M = split_len(M1, CHUNK) + Li = off_in + M1 + self.dict_prop_out, _ = dict_prop_for(max(Li, 1 << 20)) + self.dict_prop_in, _ = dict_prop_for(d + 32 + H + 8192) + st = self._build_streams(C, lc, ds, d, Ls_LB, lLB, off_in, Ls_M, + M1, H) + if st is None: + Y += 8 + continue + mseg = self._build_mseg(st, d, lc, ds, H, M) + if mseg is None: + Y += 8 + continue + M_new = len(mseg) + Y_new = len(st["hdr_bytes"]) + len(st["mech"]) + M_new + 2 + total = st["n"] + 32 + H + file_sizes = [len(x) for _, x in self.files] + sub_sizes = file_sizes + [ds] + [total] + entries = self.entries() + hdr, crc_base = self.build_header(st["n"], total, d, entries, + sub_sizes, Li) + H_new = len(hdr) + key = (Y_new, H_new, M_new) + if key in seen: # 再次见到同一组值 = 已收敛 + Y, H, M = Y_new, H_new, M_new + break + seen.add(key) + Y, H, M = Y_new, H_new, M_new + else: + raise RuntimeError("double layout 不收敛") + return {"Y": Y, "H": H, "M": M} + + # ---------- 定稿:用收敛后的 (Y, H, M) 重算全部结构 ---------- + def finalize(self, Y, H, M): + content = self.content + dc = len(content) + C = self._C # layout 里已压缩过 + lc = len(C) + ds = lc + 32 + H + Y + d = dc + ds + Ls_LB = split_len(ds, CHUNK) + lLB = 3 * len(Ls_LB) + ds + off_in = lc + lLB + M1 = M + 1 + Ls_M = split_len(M1, CHUNK) + Li = off_in + M1 + self.dict_prop_out, ds_out = dict_prop_for(max(Li, 1 << 20)) + self.dict_prop_in, ds_in = dict_prop_for(d + 32 + H + 8192) + st = self._build_streams(C, lc, ds, d, Ls_LB, lLB, off_in, Ls_M, M1, H) + mseg = self._build_mseg(st, d, lc, ds, H, M) + assert len(mseg) == M, "Mseg %d != %d" % (len(mseg), M) + total = st["n"] + 32 + H + file_sizes = [len(x) for _, x in self.files] + sub_sizes = file_sizes + [ds] + [total] + entries = self.entries() + hdr, crc_base = self.build_header(st["n"], total, d, entries, + sub_sizes, Li) + assert len(hdr) == H, "header %d != %d" % (len(hdr), H) + plant = st["hdr_bytes"] + bytes(st["mech"]) + mseg + b"\x00\x00" + assert len(plant) == Y, "plant %d != %d" % (len(plant), Y) + return {"C": C, "lc": lc, "dc": dc, "ds": ds, "d": d, "Li": Li, + "ochunks": st["ochunks"], "hdr_tab": st["hdr_tab"], + "mseg": mseg, "M": M, "H": H, "n": st["n"], "total": total, + "header": hdr, "crc_base": crc_base, "plant": plant, + "dict_size_in": ds_in, "dict_size_out": ds_out, + "n_sub": len(sub_sizes)} + + # ---------- 外层流 P 的构造 ---------- + def _build_streams(self, C, lc, ds, d, Ls_LB, lLB, off_in, Ls_M, M1, H): + hdr_tab, hdr_idx = [], {} + + def hidx(b): + assert len(b) == 3 and b[0] in (0x01, 0x02), b.hex() + if b not in hdr_idx: + hdr_idx[b] = len(hdr_tab) + hdr_tab.append(b) + return hdr_idx[b] + + ochunks = [] + f, io = 32, 0 + mech = bytearray() + + def put_lzma(tokens, ioff): + blk, t = lzma_chunk(tokens, ioff) + ochunks.append({"kind": "lzma", "foff": f, "size": len(blk), + "ioff": ioff, "olen": t, "bytes": blk, + "mech": len(mech)}) + mech.extend(blk) + return len(blk), t + + def put_store(ioff, olen, hi, src): + ochunks.append({"kind": "store", "foff": f, "size": 3 + olen, + "ioff": ioff, "olen": olen, "hdr": hi, "src": src}) + return 3 + olen + + # 段 1:store 链承载 Cseg(I[0:lc] = C 的字节;源 = seed 的 C 参照副本) + Ls_C = split_len(lc, CHUNK) + c_off = 0 + for L in Ls_C: + f += put_store(io, L, hidx(store_hdr(L, first=(c_off == 0))), + ("seed", c_off)) + io += L + c_off += L + assert io == lc + + # 段 2:LBseg(I[lc : lc+lLB])—— 内层 store 链,载荷 = seed + lb_off = lc + seed_off = 0 + for j, L in enumerate(Ls_LB): + lb_hdr = store_hdr(L, first=False) + if j == 0 or L != CHUNK: + # 没有可回引的相同样本,用外层 store chunk 原样携带这 3 字节 + f += put_store(lb_off, 3, hidx(store_hdr(3, first=False)), + ("tab", hidx(lb_hdr))) + io += 3 + else: + # 与 chunk0 的头逐字节相同,直接从 I[lc:lc+3] 复制 + n, t = put_lzma([("m", lb_off - lc, 3)], lb_off) + assert t == 3 + f += n + io += 3 + # 载荷:C 参照副本区走 rep0 回溯匹配(去重发生处),其余走 store + pay = lb_off + 3 + i = 0 + while i < L: + if seed_off + i < lc: + a = min(L - i, lc - (seed_off + i), LZ2_MAXU) + dist = (pay + i) - (seed_off + i) + n, t = put_lzma(matches_for(dist, a), pay + i) + assert t == a + f += n + io += a + i += a + else: + a = min(L - i, LZ2_MAXU) + f += put_store(pay + i, a, hidx(store_hdr(a, first=False)), + ("seed", seed_off + i)) + io += a + i += a + lb_off += 3 + L + seed_off += L + assert lb_off == lc + lLB and io == lc + lLB + + # 段 3:store 链承载 Mseg ‖ 0x00(0x00 是内层流的终止符) + m_off = 0 + for L in Ls_M: + f += put_store(off_in + m_off, L, + hidx(store_hdr(L, first=False)), ("mseg", m_off)) + io += L + m_off += L + # 外层流自己的终止符 0x00 + ochunks.append({"kind": "term", "foff": f, "size": 1, "ioff": io, + "olen": 0, "bytes": b"\x00"}) + f += 1 + return {"ochunks": ochunks, "mech": mech, "hdr_tab": hdr_tab, + "hdr_bytes": b"".join(hdr_tab), "n": f - 32} + + # ---------- 内层 Mseg:把 quine 区的每个 F 区段映射成 match 链 ---------- + def _build_mseg(self, st, d, lc, ds, H, M): + dc = d - ds + s_S32 = dc + lc # seed 里 S32 副本 + s_H = dc + lc + 32 # seed 里 H 副本 + s_tab = dc + lc + 32 + H # seed 里头样本表 + s_mech = s_tab + len(st["hdr_bytes"]) # seed 里机械串 + s_mseg = s_mech + len(st["mech"]) # seed 里 Mseg 副本 + total = st["n"] + 32 + H + hoff = 32 + st["n"] + segs = [(0, 32, s_S32)] # F[0:32) 签名头 + for c in st["ochunks"]: + if c["kind"] == "store": + segs.append((c["foff"], 3, s_tab + 3 * c["hdr"])) + src = c["src"] + if src[0] == "seed": + u = dc + src[1] + elif src[0] == "tab": + u = s_tab + 3 * src[1] + else: # ("mseg", off) + u = s_mseg + src[1] + segs.append((c["foff"] + 3, c["olen"], u)) + elif c["kind"] == "lzma": + segs.append((c["foff"], c["size"], s_mech + c["mech"])) + else: # term:并入前一个载荷段 + pf, pl, pu = segs[-1] + segs[-1] = (pf, pl + 1, pu) + segs.append((hoff, H, s_H)) # F[hoff:] 头部 + pos = 0 + for (fo, ln, u) in segs: + assert fo == pos, "段不连续: %d != %d" % (fo, pos) + assert ln >= 2, "段太短 %d @%d" % (ln, fo) + pos += ln + assert pos == total, "段总长 %d != total %d" % (pos, total) + # 生成 match 链,按 2 MiB 上限切成多个 0xC0 chunk + mseg = bytearray() + out_pos = d + cur, cur_len = [], 0 + chunks = [] + for (fo, ln, u) in segs: + dist = (d + fo) - u + assert 0 < dist, "dist=%d @%d" % (dist, fo) + toks = matches_for(dist, ln) + if cur_len + ln > LZ2_MAXU - MAX_MATCH: + chunks.append((cur, out_pos, cur_len)) + out_pos += cur_len + cur, cur_len = [], 0 + cur.extend(toks) + cur_len += ln + if cur: + chunks.append((cur, out_pos, cur_len)) + out_pos += cur_len + assert out_pos == d + total, "Mseg 输出 %d != %d" % (out_pos, d + total) + for (toks, op, cl) in chunks: + blk, t = lzma_chunk(toks, op) + assert t == cl + mseg.extend(blk) + return bytes(mseg) + + # ---------- F 中承载 seed[soff] 的那个字节的偏移 ---------- + def _f_off_of_seed(self, lay, soff): + """返回 (F 偏移, 该 store 载荷内从 soff 起还剩多少字节)。 + seed_head 超过 64 KiB 时会被切成多片,所以调用方要循环推进。""" + for c in lay["ochunks"]: + if c["kind"] == "store" and c["src"][0] == "seed": + s0 = c["src"][1] + if s0 <= soff < s0 + c["olen"]: + return c["foff"] + 3 + (soff - s0), s0 + c["olen"] - soff + raise RuntimeError("seed 偏移 %d 未被 store 载荷覆盖" % soff) + + def _f_pos_list(self, lay, soff, length): + """seed[soff:soff+length] 在 F 中对应的字节位置列表(可能跨多片)。""" + res = [] + while length > 0: + p, avail = self._f_off_of_seed(lay, soff) + a = min(length, avail) + res.extend(range(p, p + a)) + soff += a + length -= a + return res + + # ---------- 装配 ---------- + def assemble(self, lay): + total, H = lay["total"], lay["H"] + hoff = total - H + C, plant = lay["C"], lay["plant"] + F = bytearray(total) + # pass A: 签名头 + 所有非 store 载荷字节 + F[0:6] = SIG + F[6:8] = VER + struct.pack_into("<Q", F, 12, lay["n"]) + struct.pack_into("<Q", F, 20, H) + for c in lay["ochunks"]: + if c["kind"] == "store": + F[c["foff"]:c["foff"] + 3] = lay["hdr_tab"][c["hdr"]] + else: + F[c["foff"]:c["foff"] + c["size"]] = c["bytes"] + F[hoff:hoff + H] = lay["header"] + # pass B: seed = C副本 ‖ S32副本 ‖ H副本 ‖ plant + seed = bytearray() + seed += C + seed += bytes(F[0:32]) + seed += bytes(F[hoff:hoff + H]) + seed += plant + assert len(seed) == lay["ds"], "seed %d != %d" % (len(seed), lay["ds"]) + # pass C: 各 store 的载荷 + msegz = lay["mseg"] + b"\x00" + for c in lay["ochunks"]: + if c["kind"] != "store": + continue + p = c["foff"] + 3 + src, L = c["src"], c["olen"] + if src[0] == "seed": + F[p:p + L] = seed[src[1]:src[1] + L] + elif src[0] == "tab": + F[p:p + 3] = lay["hdr_tab"][src[1]] + else: + F[p:p + L] = msegz[src[1]:src[1] + L] + return F, bytes(seed) + + # ---------- CRC 定点(128x128 GF(2):seed/quine/Next/Start 四个 CRC) ---------- + def solve_crc(self, F, lay, C, plant): + H, hoff = lay["H"], lay["total"] - lay["H"] + n_sub, crc_base = lay["n_sub"], lay["crc_base"] + lc = lay["lc"] + # seed 里 S32 / H 副本在 F 中的镜像(可能跨多片,逐字节列出) + scopy0 = self._f_pos_list(lay, lc, 32) + Fv = memoryview(F) + + def seed_crc(): + v = crc32(C) + v = crc32(Fv[0:32], v) # S32 副本 + v = crc32(Fv[hoff:hoff + H], v) # H 副本 + return crc32(plant, v) + + def targets(): + return (seed_crc(), crc32(Fv), crc32(Fv[hoff:hoff + H]), + crc32(Fv[12:32])) + + # 已知:各内容文件的 CRC,写本体 + seed 里 H 副本的镜像两处 + known = [crc32(data) for _, data in self.files] + for i, e in enumerate(known): + slot = crc_base + 4 * i + b = struct.pack("<I", e) + for k in range(4): + F[hoff + slot + k] = b[k] + mir = self._f_pos_list(lay, lc + 32 + slot, 4) + assert len(mir) == 4 + for k in range(4): + F[mir[k]] = b[k] + # 未知量:D_seed(seed 的 CRC)、D(quine 的 CRC)、N、S + # 每个未知量 4 字节,每字节有"本体 + seed 镜像"两个落点 + qs = crc_base + 4 * len(known) # seed 子流的 CRC 槽 + q = crc_base + 4 * (n_sub - 1) # quine 子流的 CRC 槽 + groups = [] + for slot in (qs, q): + groups.append([list(range(hoff + slot, hoff + slot + 4)), + self._f_pos_list(lay, lc + 32 + slot, 4)]) + groups.append([list(range(28, 32)), scopy0[28:32]]) # NextHeaderCRC + groups.append([list(range(8, 12)), scopy0[8:12]]) # StartHeaderCRC + nb = 32 * len(groups) + base = targets() + basevec = 0 + for i, v in enumerate(base): + basevec |= v << (32 * i) + cols = [] + for g in range(len(groups)): + own, mir = groups[g] + for kb in range(32): + bi, bb = kb // 8, kb % 8 + poss = [own[bi], mir[bi]] + for p in poss: + F[p] ^= (1 << bb) + t = targets() + for p in poss: + F[p] ^= (1 << bb) + delta = 0 + for i, v in enumerate(t): + delta |= (v ^ base[i]) << (32 * i) + cols.append(delta) + eqs = [] + for i in range(nb): + coeff = 0 + for j in range(nb): + if (cols[j] >> i) & 1: + coeff |= 1 << j + coeff ^= 1 << i + eqs.append([coeff, (basevec >> i) & 1]) + for j in range(nb): + p = next((i for i in range(j, nb) if (eqs[i][0] >> j) & 1), None) + if p is None: + raise RuntimeError("GF(2) 奇异 @bit%d" % j) + eqs[j], eqs[p] = eqs[p], eqs[j] + for i in range(nb): + if i != j and ((eqs[i][0] >> j) & 1): + eqs[i][0] ^= eqs[j][0] + eqs[i][1] ^= eqs[j][1] + x = 0 + for i in range(nb): + assert eqs[i][0] == (1 << i) + if eqs[i][1]: + x |= 1 << i + vals = [(x >> (32 * i)) & 0xFFFFFFFF for i in range(len(groups))] + for g in range(len(groups)): + own, mir = groups[g] + b = struct.pack("<I", vals[g]) + for k in range(4): + F[own[k]] = b[k] + F[mir[k]] = b[k] + t = targets() + assert t == tuple(vals), "CRC 定点失败: %s != %s" % (t, vals) + return vals + + def build(self): + l0 = self.layout() + lay = self.finalize(l0["Y"], l0["H"], l0["M"]) + F, seed = self.assemble(lay) + crcs = self.solve_crc(F, lay, lay["C"], lay["plant"]) + # CRC 定点会改写 H / S32,而 seed 是它们的镜像,定点后需重建 + hoff = lay["total"] - lay["H"] + seed = lay["C"] + bytes(F[0:32]) + bytes(F[hoff:hoff + lay["H"]]) \ + + lay["plant"] + return bytes(F), lay, seed, crcs + + +def verify_double(F, lay, files, seed, content): + """串联两个原始 LZMA2 解码器还原 U,逐段校验。""" + d, total = lay["d"], lay["total"] + dec_o = lzma.LZMADecompressor( + format=lzma.FORMAT_RAW, + filters=[{"id": lzma.FILTER_LZMA2, "dict_size": lay["dict_size_out"]}]) + I = dec_o.decompress(F[32:32 + lay["n"]]) + ok = True + if len(I) != lay["Li"]: + print("[verify] 外层输出 %d != I %d" % (len(I), lay["Li"])) + return False + dec_i = lzma.LZMADecompressor( + format=lzma.FORMAT_RAW, + filters=[{"id": lzma.FILTER_LZMA2, "dict_size": lay["dict_size_in"]}]) + U = dec_i.decompress(I) + exp = d + total + if len(U) != exp: + print("[verify] 内层输出 %d != %d" % (len(U), exp)) + return False + dc, ds = lay["dc"], lay["ds"] + if U[:dc] != content: + print("[verify] 内容不匹配") + ok = False + pos = 0 + for rel, data in files: # 内容文件排在 U 的最前面 + if U[pos:pos + len(data)] != data: + print("[verify] 文件不匹配:", rel) + ok = False + pos += len(data) + assert pos == dc + if U[dc:dc + ds] != seed: + print("[verify] seed 不匹配") + ok = False + if U[d:] != F: + print("[verify] quine 自复制不匹配") + ok = False + print("[verify] 自解码: |I|=%d, |U|=%d, seed/文件/quine 全部匹配: %s" + % (len(I), len(U), ok)) + return ok +``` + 仅仅是大佬的一句话,AI就能做出来,实在是太可怕了。最终我试了一下,官方的7-Zip可以正常解压,但是Windows资源管理器不行……Windows资源管理器使用的也是[libarchive](https://github.com/libarchive/libarchive),似乎是因为libarchive只支持2个解码器,并且[第二个解码器只能是像BCJ这样的过滤器](https://github.com/libarchive/libarchive/blob/8bb3bbdc7b117a1e22086a2260f2087aafa90687/libarchive/archive_read_support_format_7zip.c#L1475)……明明7-Zip官方是可以解压的,不知道如果把这个问题当作BUG报告给libarchive他们会不会解决?但目前存在兼容性问题的话我博客压缩包就先不用这个方案了吧🥲…… ## 对TXZ格式的尝试 在做完7z格式的压缩包之后,我发现了一个问题,虽然7z确实很流行,但是在Linux下解压起来有点麻烦,7-Zip历史上主要面向Windows,Linux上长期以来更多依赖p7zip等第三方移植,因此生态集成度不如tar.xz,想要解压7z文件还得额外安装。 不过Linux下也有个支持LZMA2算法的压缩软件,那就是前些年出过[后门](https://tukaani.org/xz-backdoor/)的XZ Utils,配合tar就可以做出TXZ(tar.xz)文件,甚至用我[博客终端](https://mabbs.github.io/linux/)中的BusyBox也能解压。我想了一下反正有AI,干脆一句话让AI帮我把blogquine.py改成tar.xz格式的好了,结果倒也没费多少功夫,AI就这样写出来了: |
