feat(sec): 签名鉴权 2B (agent-221) — meow_verify 多公钥数组+v2签名块(含ts,未来宽限,兼容v1)+meow_sign verify子命令+产签README; svc_power 面板身份精确路径绑定(删启发式,3反例验证)
meow_verify→6c2e8ed2; svc_power→306df962; qemu+宿主全过
This commit is contained in:
1 parent
249b6224ab
commit
05a19a9ea3
13 files changed
+497
-78
No files matched your search
@@ -1,8 +1,8 @@
|
||||
/* meow_sig.h — .mpk 签名块格式(MPK_SIGNATURE_DESIGN §3.1)+ 被签消息构造(§3.1)。
|
||||
/* meow_sig.h — .mpk 签名块格式(MPK_SIGNATURE_DESIGN §3.1,2B 扩展 §7)+ 被签消息构造。
|
||||
*
|
||||
* .mpk = [ tar.gz bytes ......................... ] [ meow_sig_block(定长 LE)]
|
||||
* .mpk = [ tar.gz bytes ......................... ] [ meow_sig_block(变长 LE,v1/v2)]
|
||||
*
|
||||
* meow_sig_block(packed,总长 MEOW_SIG_BLOCK_LEN):
|
||||
* meow_sig_block v1(packed,总长 MEOW_SIG_BLOCK_LEN_V1=180):
|
||||
* char magic[8]; "MEOWSIG1"
|
||||
* uint8_t alg; 1 = ed25519
|
||||
* uint8_t flags; 0
|
||||
@@ -11,10 +11,21 @@
|
||||
* uint8_t payload_sha256[32];sha256(整个 .mpk 去掉尾部 footer 的其余字节)
|
||||
* uint8_t sig[64]; Ed25519(pk, msg)
|
||||
* uint32_t msg_len; 实际签名的 msg 字节数(LE)
|
||||
* uint32_t block_len; 本块总长(LE;= MEOW_SIG_BLOCK_LEN)
|
||||
* uint32_t block_len; 本块总长(LE;= MEOW_SIG_BLOCK_LEN_V1)
|
||||
*
|
||||
* 被签消息 msg = "MEOWSIG1" || alg(1B) || package_len(4B,LE) || package || payload_sha256(32B)。
|
||||
* 本文件由 meow_verify 与 meow_sign 共用(meow_sign 用相对路径 include)。 */
|
||||
* meow_sig_block v2(packed,总长 MEOW_SIG_BLOCK_LEN_V2=184;2B 加固):
|
||||
* 在 v1 的 sig 后、msg_len 前插入 uint32_t ts(unix 秒,LE,**纳入被签消息**)。
|
||||
* 前 172 字节(magic/alg/flags/pad/package/payload_sha256/sig)与 v1 完全同偏移,
|
||||
* 故验签端可据尾部 block_len(v1=180 / v2=184)判别版本后按偏移取字段。
|
||||
* flags bit0 (MEOW_SIG_FLAG_TS)=1 标记含时间戳。
|
||||
*
|
||||
* 被签消息:
|
||||
* v1 msg = "MEOWSIG1" || alg(1B) || package_len(4B,LE) || package || payload_sha256(32B)。
|
||||
* v2 msg = v1 msg || ts(4B,LE)。 — 时间戳被签名绑定,防改时间戳。
|
||||
*
|
||||
* 本文件由 meow_verify 与 meow_sign 共用(meow_sign 用相对路径 include)。
|
||||
* v1/v2 兼容:验签端读 v1(旧 2A 包)不检时间戳(无该字段),读 v2(2B 包)检 ts 未来宽限。
|
||||
* (明确不做:防重放/过期——ts 只做「未来异常」宽限拒绝,见 MPK_SIGNATURE_DESIGN §8 诚实标注。) */
|
||||
#ifndef MEOW_SIG_H
|
||||
#define MEOW_SIG_H
|
||||
|
||||
@@ -28,6 +39,9 @@
|
||||
#define MEOW_SIG_SHA256_LEN 32
|
||||
#define MEOW_SIG_SIG_LEN 64
|
||||
|
||||
/* flags 位(v2) */
|
||||
#define MEOW_SIG_FLAG_TS 0x01u /* 含签名时间戳(v2) */
|
||||
|
||||
typedef struct __attribute__((packed)) {
|
||||
uint8_t magic[MEOW_SIG_MAGIC_LEN];
|
||||
uint8_t alg;
|
||||
@@ -40,7 +54,34 @@ typedef struct __attribute__((packed)) {
|
||||
uint32_t block_len;
|
||||
} meow_sig_block_t;
|
||||
|
||||
#define MEOW_SIG_BLOCK_LEN (sizeof(meow_sig_block_t)) /* 定长 180 */
|
||||
typedef struct __attribute__((packed)) {
|
||||
uint8_t magic[MEOW_SIG_MAGIC_LEN];
|
||||
uint8_t alg;
|
||||
uint8_t flags;
|
||||
uint16_t pad;
|
||||
char package[MEOW_SIG_PKG_MAX];
|
||||
uint8_t payload_sha256[MEOW_SIG_SHA256_LEN];
|
||||
uint8_t sig[MEOW_SIG_SIG_LEN];
|
||||
uint32_t ts; /* v2: unix 时间戳(LE,被签名) */
|
||||
uint32_t msg_len;
|
||||
uint32_t block_len;
|
||||
} meow_sig_block_v2_t;
|
||||
|
||||
/* 块版本:由尾部 block_len 判别(v1=180 无 ts;v2=184 含 ts) */
|
||||
#define MEOW_SIG_BLOCK_LEN_V1 (sizeof(meow_sig_block_t)) /* 180 */
|
||||
#define MEOW_SIG_BLOCK_LEN_V2 (sizeof(meow_sig_block_v2_t)) /* 184 = 180 + ts(4) */
|
||||
#define MEOW_SIG_BLOCK_MAX MEOW_SIG_BLOCK_LEN_V2
|
||||
|
||||
/* 签名时间戳未来宽限(秒):ts 在 now+宽限内视为合法时钟误差,超出即拒。 */
|
||||
#define MEOW_SIG_TS_GRACE 86400u /* 24h */
|
||||
|
||||
/* 字段偏移(前 172B 两版同偏移;ts/msg_len 因版本异,见下)。 */
|
||||
#define MEOW_SIG_OFF_PKG 12
|
||||
#define MEOW_SIG_OFF_SHA 76
|
||||
#define MEOW_SIG_OFF_SIG 108
|
||||
#define MEOW_SIG_OFF_TS 172 /* v2 only */
|
||||
#define MEOW_SIG_OFF_MSGLEN_V1 (MEOW_SIG_BLOCK_LEN_V1 - 8) /* 172 */
|
||||
#define MEOW_SIG_OFF_MSGLEN_V2 (MEOW_SIG_BLOCK_LEN_V2 - 8) /* 176 */
|
||||
|
||||
/* 按字节读取 LE 的 uint32(避免 packed 解引用对齐告警) */
|
||||
static inline uint32_t meow_le32(const uint8_t *p)
|
||||
@@ -56,9 +97,10 @@ static inline void meow_le32_put(uint8_t *p, uint32_t v)
|
||||
p[3] = (uint8_t)((v >> 24) & 0xff);
|
||||
}
|
||||
|
||||
#define MEOW_SIG_MSG_MAX (MEOW_SIG_MAGIC_LEN + 1 + 4 + MEOW_SIG_PKG_MAX + MEOW_SIG_SHA256_LEN)
|
||||
/* v1 或 v2 的 msg 均不超过此上限(v1 109 / v2 113)。 */
|
||||
#define MEOW_SIG_MSG_MAX (MEOW_SIG_MAGIC_LEN + 1 + 4 + MEOW_SIG_PKG_MAX + MEOW_SIG_SHA256_LEN + 4)
|
||||
|
||||
/* 按设计构造被签消息 msg = "MEOWSIG1" || alg(1B) || package_len(4B,LE) || package || payload_sha256(32B)。
|
||||
/* 按设计构造 v1 被签消息 msg = "MEOWSIG1" || alg(1B) || package_len(4B,LE) || package || payload_sha256(32B)。
|
||||
* 返回 msg 字节数。签名端与验签端必须用同一构造(meow_sign / meow_verify 共用)。 */
|
||||
static inline unsigned meow_sig_msg_build(char *out, const char *package,
|
||||
const uint8_t payload_sha256[MEOW_SIG_SHA256_LEN])
|
||||
@@ -74,4 +116,14 @@ static inline unsigned meow_sig_msg_build(char *out, const char *package,
|
||||
return o;
|
||||
}
|
||||
|
||||
/* 构造 v2 被签消息 = v1 msg || ts(4B,LE)。返回 msg 字节数(= v1 msg + 4)。 */
|
||||
static inline unsigned meow_sig_msg_build_v2(char *out, const char *package,
|
||||
const uint8_t payload_sha256[MEOW_SIG_SHA256_LEN],
|
||||
uint32_t ts)
|
||||
{
|
||||
unsigned o = meow_sig_msg_build(out, package, payload_sha256);
|
||||
meow_le32_put((uint8_t *)out + o, ts); o += 4;
|
||||
return o;
|
||||
}
|
||||
|
||||
#endif /* MEOW_SIG_H */
|
||||
@@ -1,17 +1,27 @@
|
||||
/* meow_signing_pub.h — 固件公钥(Ed25519 32B,编译期固化进 meow_verify)。
|
||||
* 由 `meow_sign keygen` 生成(.keys/signing.key.pub),本头只含【公钥】,可入库;
|
||||
* 私钥仅在 .keys/(已加入 .gitignore,绝不入库/报告)。轮换公钥=重生成本头+重编 meow_verify。 */
|
||||
* 私钥仅在 .keys/(已加入 .gitignore,绝不入库/报告)。
|
||||
*
|
||||
* 2B 多钥兼容(MPK_SIGNATURE_DESIGN §4.3 轮换铺路):固件内嵌**公钥数组**,验签时任一公钥通过即放行。
|
||||
* 轮换/增补公钥=重写本头数组(g_meow_pub[MEOW_PUB_KEY_COUNT][])+重编 meow_verify(固件更新)。
|
||||
* 保持旧钥在数组前部可作「跨代兼容」(旧钥签的包在新固件仍验过);从尾部追加新钥;
|
||||
* 若某钥彻底作废,从数组移除即可(注意:会令旧钥签的包在新固件拒装——轮换需与包重签协同)。
|
||||
* MEOW_PUB_KEY_COUNT 为当前内嵌公钥数(可增)。 */
|
||||
#ifndef MEOW_SIGNING_PUB_H
|
||||
#define MEOW_SIGNING_PUB_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
static const uint8_t g_meow_pub[32] =
|
||||
#define MEOW_PUB_KEY_COUNT 1 /* 当前固件内嵌公钥数;增补即在数组追加并 +1、重编 meow_verify */
|
||||
|
||||
static const uint8_t g_meow_pub[MEOW_PUB_KEY_COUNT][32] =
|
||||
{
|
||||
0x22, 0xa7, 0x83, 0xac, 0x28, 0xd3, 0x25, 0x6d,
|
||||
0x3f, 0x84, 0x72, 0x72, 0x50, 0x5b, 0x2c, 0x61,
|
||||
0x60, 0x97, 0xff, 0xc3, 0x98, 0x78, 0x14, 0x9d,
|
||||
0xc7, 0x37, 0x8c, 0x58, 0x72, 0x26, 0x37, 0xf2
|
||||
{ /* key #0:维护者主钥(.keys/signing.key.pub;与 2A 同钥,跨代兼容) */
|
||||
0x22, 0xa7, 0x83, 0xac, 0x28, 0xd3, 0x25, 0x6d,
|
||||
0x3f, 0x84, 0x72, 0x72, 0x50, 0x5b, 0x2c, 0x61,
|
||||
0x60, 0x97, 0xff, 0xc3, 0x98, 0x78, 0x14, 0x9d,
|
||||
0xc7, 0x37, 0x8c, 0x58, 0x72, 0x26, 0x37, 0xf2
|
||||
}
|
||||
};
|
||||
|
||||
#endif /* MEOW_SIGNING_PUB_H */
|
||||
Binary file not shown.
@@ -1,12 +1,15 @@
|
||||
/* meow_verify.c — MeowOS .mpk 签名校验器(固件 /usr/bin/meow_verify,静态 mipsel)。
|
||||
*
|
||||
* 功能(MPK_SIGNATURE_DESIGN §5.1):
|
||||
* - Ed25519 验签(TweetNaCl crypto_sign_open,公钥编译期固化进 meow_signing_pub.h);
|
||||
* 功能(MPK_SIGNATURE_DESIGN §5.1 + 2B §7):
|
||||
* - Ed25519 验签(TweetNaCl crypto_sign_open,公钥编译期固化进 meow_signing_pub.h,**多钥数组**);
|
||||
* - payload_sha256 = SHA-256(.mpk 去掉尾部 footer 的其余字节,即 tar.gz 前缀,分块读、无需解包);
|
||||
* - 包名绑定①:footer.package == 期望包名(--package 或文件名茎);
|
||||
* - 被签消息 msg = "MEOWSIG1" || alg(1B) || package_len(4B,LE) || package || payload_sha256(32B)。
|
||||
* - 被签消息:v1 msg = "MEOWSIG1"||alg||pkg_len||package||payload_sha256;v2 msg = v1||ts(4B,LE)。
|
||||
* 2B 加固:多公钥(任一通过即放行,为轮换铺路);v2 块含**签名时间戳 ts**,超未来宽限即拒
|
||||
* (MEOW_SIG_TS_GRACE=24h;只做「未来异常」拒,防重放/过期明确不做)。
|
||||
* 绑定②(app.json.package)与③(os.meow.* 前缀)由调用方(nyai / launcher)在安装流里执行,
|
||||
* 本器只保证「有签名就必须验签通过」。见 MPK_SIGNATURE_DESIGN §3.3(分工诚实标注)。
|
||||
* 无签名第三方包安装放行由调用方决定,本器对无 footer 返回 2(调用方据分级处理)。
|
||||
*
|
||||
* 用法:
|
||||
* meow_verify <mpk> # 验签(默认系统模式:固件公钥 + 绑定①)
|
||||
@@ -15,7 +18,7 @@
|
||||
* meow_verify --has-sig <mpk> # 只探测是否存在 MEOWSIG1 footer:输出 yes/no
|
||||
* meow_verify --strip <mpk> # 输出去 footer 的干净 tar.gz 到 stdout(无 footer 则原样复制)
|
||||
*
|
||||
* 退出码:0=通过;1=有签但不通过(篡改/包名不符/公钥不符/格式错);2=无签名 footer;3=用法/IO 错误。
|
||||
* 退出码:0=通过;1=有签但不通过(篡改/包名不符/公钥不符/格式错/ts异常);2=无签名 footer;3=用法/IO 错误。
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
@@ -23,12 +26,14 @@
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <sys/stat.h>
|
||||
#include <time.h>
|
||||
|
||||
#include "tweetnacl.h"
|
||||
#include "sha256.h"
|
||||
#include "meow_sig.h"
|
||||
|
||||
/* 固件公钥(编译期固化,32B Ed25519)。由 meow_sign keygen 生成后写死于此头。 */
|
||||
/* 固件公钥数组(编译期固化,多钥 Ed25519)。由 meow_sign keygen 生成后写死于此头;
|
||||
* 轮换/增补公钥=改数组+MEOW_PUB_KEY_COUNT+重编 meow_verify(见 meow_signing_pub.h)。 */
|
||||
#include "meow_signing_pub.h"
|
||||
|
||||
/* 验签侧绝不调用 keypair,但 tweetnacl.c 的 crypto_sign_keypair 引用了 randombytes;
|
||||
@@ -46,17 +51,22 @@ static int file_size(const char *path, long long *sz)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* 读文件尾部 MEOW_SIG_BLOCK_LEN 字节作为 footer。返回 0 成功,-2 文件太短(无签名空间),-1 IO 错。 */
|
||||
static int read_footer(const char *path, long long fsize, meow_sig_block_t *blk)
|
||||
/* 读文件尾部签名块:先读最后 4 字节 block_len 判版本(v1=180 / v2=184),再整块读入 buf。
|
||||
* 返回实际块字节数(>0);-2 太短/块长非法(无签名空间);-1 IO 错。magic 校验留给调用方。 */
|
||||
static int read_block_bytes(const char *path, long long fsize, uint8_t *buf, int bufn)
|
||||
{
|
||||
if (fsize < (long long)MEOW_SIG_BLOCK_LEN) return -2;
|
||||
int fd = open(path, O_RDONLY);
|
||||
if (fd < 0) return -1;
|
||||
if (lseek(fd, fsize - (long long)MEOW_SIG_BLOCK_LEN, SEEK_SET) < 0) { close(fd); return -1; }
|
||||
ssize_t n = read(fd, blk, MEOW_SIG_BLOCK_LEN);
|
||||
uint8_t bl4[4];
|
||||
if (lseek(fd, fsize - 4, SEEK_SET) < 0) { close(fd); return -1; }
|
||||
if (read(fd, bl4, 4) != 4) { close(fd); return -1; }
|
||||
uint32_t blen = meow_le32(bl4);
|
||||
if (blen != MEOW_SIG_BLOCK_LEN_V1 && blen != MEOW_SIG_BLOCK_LEN_V2) { close(fd); return -2; }
|
||||
if (fsize < (long long)blen || (int)blen > bufn) { close(fd); return -2; }
|
||||
if (lseek(fd, fsize - (long long)blen, SEEK_SET) < 0) { close(fd); return -1; }
|
||||
if (read(fd, buf, blen) != (ssize_t)blen) { close(fd); return -1; }
|
||||
close(fd);
|
||||
if (n != (ssize_t)MEOW_SIG_BLOCK_LEN) return -1;
|
||||
return 0;
|
||||
return (int)blen;
|
||||
}
|
||||
|
||||
/* 分块 SHA-256 计算文件前 plen 字节。返回 0 成功,-1 IO/读错。 */
|
||||
@@ -98,51 +108,80 @@ static int verify_mpk(const char *mpk, const char *pkg)
|
||||
{
|
||||
long long fsize;
|
||||
if (file_size(mpk, &fsize) != 0) return 3;
|
||||
if (fsize < (long long)MEOW_SIG_BLOCK_LEN) return 2; /* 无签名空间 */
|
||||
if (fsize < (long long)MEOW_SIG_BLOCK_LEN_V1) return 2; /* 无签名空间 */
|
||||
|
||||
meow_sig_block_t blk;
|
||||
if (read_footer(mpk, fsize, &blk) != 0) return 3;
|
||||
if (memcmp(blk.magic, MEOW_SIG_MAGIC, MEOW_SIG_MAGIC_LEN) != 0) return 2; /* 无 MEOWSIG1 footer */
|
||||
if (blk.alg != MEOW_SIG_ALG_ED25519 || blk.block_len != MEOW_SIG_BLOCK_LEN) return 1; /* 格式错 */
|
||||
uint8_t buf[MEOW_SIG_BLOCK_MAX];
|
||||
int blen = read_block_bytes(mpk, fsize, buf, sizeof buf);
|
||||
if (blen < 0) return blen == -2 ? 2 : 3;
|
||||
if (memcmp(buf, MEOW_SIG_MAGIC, MEOW_SIG_MAGIC_LEN) != 0) return 2; /* 无 MEOWSIG1 footer */
|
||||
if (buf[8] != MEOW_SIG_ALG_ED25519) return 1; /* 算法不符 */
|
||||
|
||||
char pkgbuf[MEOW_SIG_PKG_MAX];
|
||||
int v2 = (blen == (int)MEOW_SIG_BLOCK_LEN_V2);
|
||||
if (!v2 && blen != (int)MEOW_SIG_BLOCK_LEN_V1) return 1; /* 块长未知:格式错 */
|
||||
uint8_t want_flags = v2 ? MEOW_SIG_FLAG_TS : 0;
|
||||
if ((buf[9] & MEOW_SIG_FLAG_TS) != want_flags) return 1; /* flags 与版本不符 */
|
||||
|
||||
char pkgsig[MEOW_SIG_PKG_MAX + 1];
|
||||
memcpy(pkgsig, buf + MEOW_SIG_OFF_PKG, MEOW_SIG_PKG_MAX);
|
||||
pkgsig[MEOW_SIG_PKG_MAX] = 0; /* 保证 NUL 终止 */
|
||||
|
||||
char pkgbuf[MEOW_SIG_PKG_MAX + 1];
|
||||
if (pkg && *pkg) {
|
||||
snprintf(pkgbuf, sizeof pkgbuf, "%s", pkg);
|
||||
} else {
|
||||
if (derive_pkg(mpk, pkgbuf, sizeof pkgbuf) != 0) return 3;
|
||||
}
|
||||
blk.package[MEOW_SIG_PKG_MAX - 1] = 0; /* 保证 NUL 终止 */
|
||||
/* 绑定①:期望包名 == footer.package */
|
||||
if (strcmp(pkgbuf, blk.package) != 0) {
|
||||
fprintf(stderr, "meow_verify: package mismatch (want %s, sig %s)\n", pkgbuf, blk.package);
|
||||
if (strcmp(pkgbuf, pkgsig) != 0) {
|
||||
fprintf(stderr, "meow_verify: package mismatch (want %s, sig %s)\n", pkgbuf, pkgsig);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* payload 哈希 */
|
||||
long long plen = fsize - (long long)MEOW_SIG_BLOCK_LEN;
|
||||
long long plen = fsize - (long long)blen;
|
||||
uint8_t sha[MEOW_SIG_SHA256_LEN];
|
||||
if (sha256_prefix(mpk, plen, sha) != 0) return 3;
|
||||
if (memcmp(sha, blk.payload_sha256, MEOW_SIG_SHA256_LEN) != 0) {
|
||||
if (memcmp(buf + MEOW_SIG_OFF_SHA, sha, MEOW_SIG_SHA256_LEN) != 0) {
|
||||
fprintf(stderr, "meow_verify: payload sha256 mismatch (content tampered)\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* 重组被签消息 + 验签 */
|
||||
/* 重组被签消息(v2 含 ts)+ 验签(多公钥,任一通过即放行) */
|
||||
uint32_t ts = v2 ? meow_le32(buf + MEOW_SIG_OFF_TS) : 0;
|
||||
char msg[MEOW_SIG_MSG_MAX];
|
||||
unsigned mlen = meow_sig_msg_build(msg, blk.package, blk.payload_sha256);
|
||||
if (blk.msg_len != mlen) { fprintf(stderr, "meow_verify: msg_len field mismatch\n"); return 1; }
|
||||
unsigned mlen;
|
||||
if (v2) mlen = meow_sig_msg_build_v2(msg, pkgsig, sha, ts);
|
||||
else mlen = meow_sig_msg_build(msg, pkgsig, sha);
|
||||
uint32_t blk_msglen = meow_le32(buf + (v2 ? MEOW_SIG_OFF_MSGLEN_V2 : MEOW_SIG_OFF_MSGLEN_V1));
|
||||
if (blk_msglen != mlen) { fprintf(stderr, "meow_verify: msg_len field mismatch\n"); return 1; }
|
||||
|
||||
uint8_t sm[MEOW_SIG_SIG_LEN + MEOW_SIG_MSG_MAX];
|
||||
memcpy(sm, blk.sig, MEOW_SIG_SIG_LEN);
|
||||
memcpy(sm, buf + MEOW_SIG_OFF_SIG, MEOW_SIG_SIG_LEN);
|
||||
memcpy(sm + MEOW_SIG_SIG_LEN, msg, mlen);
|
||||
uint8_t out[MEOW_SIG_SIG_LEN + MEOW_SIG_MSG_MAX];
|
||||
unsigned long long outlen = 0;
|
||||
if (crypto_sign_open(out, &outlen, sm, (unsigned long long)(MEOW_SIG_SIG_LEN + mlen), g_meow_pub) != 0) {
|
||||
int ok = 0;
|
||||
for (int i = 0; i < MEOW_PUB_KEY_COUNT; i++) {
|
||||
unsigned long long outlen = 0;
|
||||
if (crypto_sign_open(out, &outlen, sm, (unsigned long long)(MEOW_SIG_SIG_LEN + mlen),
|
||||
g_meow_pub[i]) == 0) { ok = 1; break; }
|
||||
}
|
||||
if (!ok) {
|
||||
fprintf(stderr, "meow_verify: ed25519 signature invalid\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
printf("%s\n", blk.package);
|
||||
/* 2B:v2 块签名时间戳未来宽限校验(仅防「未来异常」,防重放/过期不做) */
|
||||
if (v2) {
|
||||
if (ts == 0) { fprintf(stderr, "meow_verify: ts field is zero (malformed)\n"); return 1; }
|
||||
time_t now = time(NULL);
|
||||
if ((time_t)ts > now + (time_t)MEOW_SIG_TS_GRACE) {
|
||||
fprintf(stderr, "meow_verify: signature ts in future beyond grace (ts=%u now=%ld)\n",
|
||||
ts, (long)now);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
printf("%s\n", pkgsig);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -153,11 +192,11 @@ static int strip_mpk(const char *mpk)
|
||||
if (file_size(mpk, &fsize) != 0) return 3;
|
||||
long long payload = fsize;
|
||||
int has_sig = 0;
|
||||
if (fsize >= (long long)MEOW_SIG_BLOCK_LEN) {
|
||||
meow_sig_block_t blk;
|
||||
if (read_footer(mpk, fsize, &blk) == 0 &&
|
||||
memcmp(blk.magic, MEOW_SIG_MAGIC, MEOW_SIG_MAGIC_LEN) == 0) {
|
||||
payload = fsize - (long long)MEOW_SIG_BLOCK_LEN;
|
||||
if (fsize >= (long long)MEOW_SIG_BLOCK_LEN_V1) {
|
||||
uint8_t buf[MEOW_SIG_BLOCK_MAX];
|
||||
int blen = read_block_bytes(mpk, fsize, buf, sizeof buf);
|
||||
if (blen >= 0 && memcmp(buf, MEOW_SIG_MAGIC, MEOW_SIG_MAGIC_LEN) == 0) {
|
||||
payload = fsize - (long long)blen;
|
||||
has_sig = 1;
|
||||
}
|
||||
}
|
||||
@@ -180,10 +219,11 @@ static int has_sig(const char *mpk)
|
||||
{
|
||||
long long fsize;
|
||||
if (file_size(mpk, &fsize) != 0) return 3;
|
||||
if (fsize < (long long)MEOW_SIG_BLOCK_LEN) { printf("no\n"); return 2; }
|
||||
meow_sig_block_t blk;
|
||||
if (read_footer(mpk, fsize, &blk) != 0) { printf("no\n"); return 2; }
|
||||
int h = (memcmp(blk.magic, MEOW_SIG_MAGIC, MEOW_SIG_MAGIC_LEN) == 0);
|
||||
if (fsize < (long long)MEOW_SIG_BLOCK_LEN_V1) { printf("no\n"); return 2; }
|
||||
uint8_t buf[MEOW_SIG_BLOCK_MAX];
|
||||
int blen = read_block_bytes(mpk, fsize, buf, sizeof buf);
|
||||
if (blen < 0) { printf("no\n"); return 2; }
|
||||
int h = (memcmp(buf, MEOW_SIG_MAGIC, MEOW_SIG_MAGIC_LEN) == 0);
|
||||
printf(h ? "yes\n" : "no\n");
|
||||
return h ? 0 : 2;
|
||||
}
|
||||
|
||||
Binary file not shown.
Reference in new issue
Block a user