Help us shape the future of Go! Take the 2026 Go Developer Survey

ofd-signer-demo

command
v0.1.8 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Oct 31, 2026 License: Apache-2.0 Imports: 13 Imported by: 0

README

ofd-signer-demo

ofd-signer-demo 是 github.com/zc310/ofd 提供的最小演示签名器,用于说明 ofd-creator merge --sign-cmd 协议需要 实现什么,以及 SignedValue.dat 的 SES 结构。

需要 Go 1.26 或更高版本。提交推送到 GitHub 后,可在仓库外安装 main 分支版本;也可在仓库根目录安装当前检出的源码:

# 远程 main 分支
go install github.com/zc310/ofd/cmd/ofd-signer-demo@main
# 当前本地检出:在仓库根目录执行
go install ./cmd/ofd-signer-demo

程序安装到 GOBIN,未设置时为 $(go env GOPATH)/bin;请确保该目录位于 PATH 中。

SES 结构(V4)

输出遵循 GM/T 0031 的 V4 电子印章结构,与 ../../testdata/ofdrw/999.ofd 等真实样例一致:

SES_Signature ::= SEQUENCE {
    tbsSign            TBS_Sign,
    certificate        OCTET STRING,
    signatureAlgorithm OBJECT IDENTIFIER,   -- 1.2.156.10197.1.501 (SM2-with-SM3)
    signData           BIT STRING
}
TBS_Sign ::= SEQUENCE {
    version     INTEGER,                    -- 4
    eseal       SESeal,
    timeInfo    GeneralizedTime,
    dataHash    BIT STRING,                 -- Signature.xml 的 SM3 摘要
    propertyInfo IA5String                   -- 签名 XML 包内路径
}
SESeal ::= SEQUENCE {
    esealInfo           SES_Seal_Info,
    cert                OCTET STRING,
    signatureAlgorithm  OBJECT IDENTIFIER,
    signData            BIT STRING
}
SES_Seal_Info ::= SEQUENCE {
    header    SES_Header,
    esID      IA5String,
    property  SES_ESPropertyInfo,
    picture   SES_ESPictrueInfo
}
SES_Header ::= SEQUENCE {
    id      IA5String,                      -- 固定值 "ES"
    version INTEGER,                        -- 4
    vid     IA5String                       -- 厂商标识
}

注意 SES_Header.ID 是固定值 "ES",不是签名 ID;SES_Header.Version 与 TBS_Sign.Version 都是 4。把签名 ID 填进 SES_Header.ID 会导致其他工具报 invalid ses header。

来源标识

演示签名器把项目来源写入签名结构,便于确认签名是由本项目制作的:

  • --version / --help 输出 ofd-signer-demo 0.1.0 (github.com/zc310/ofd);
  • 生成的 SES_Seal_Info:
    • Header.VID = "ofd-signer-demo/0.1.0";
    • ESID = "ofd-signer-demo-<sign-id>@github.com/zc310/ofd"(esID 是厂商自定义标识);
    • Property.Name = "ofd-signer-demo 0.1.0 (演示印章, github.com/zc310/ofd)";
  • TBS_Sign.PropertyInfo = "/Doc_0/Signatures/Signature_<sign-id>.xml"(签名 XML 包内路径);
  • 自签名证书主体和签发者均为 ofd-signer-demo (github.com/zc310/ofd)。

internal/parser 解析 SignedValue.dat 后可从 SES.TBS.Seal.SealInfo.ESID、 SES.TBS.Seal.SealInfo.Property.Name 和证书主体读到这些标识。

用途

它从标准输入读取 ofd-creator 生成的 Signature.xml,向标准输出写出 SignedValue.dat。运行时不读取任何密钥或证书文件,所有材料都在进程内生成:

  • 现场生成一对 SM2 私钥/公钥;

  • 用自签名证书封装公钥(SM2WithSM3);

  • 计算 Signature.xml 的 SM3 摘要作为 TBS_Sign.DataHash;

  • 用 SM2 分别签署 SES_Seal_Info(印章内部签名)和 TBS_Sign(外层签名);

  • 现场渲染一张 PNG 印章图(SES_ESPictrueInfo.Type = "png"):由 internal/sealimg 生成的双线圆章,顶部「OFD 测试专用章」、底部「非正式印章」、中心 五角星及其下方的「zc310/ofd」小字,图片为 512×512 像素; SES_ESPictrueInfo.Width/Height 按 GB/T 38540-2020 §6.1.2.5 写为 40×40 毫米。

    这张图自带「非正式印章」声明,因此可以被单独复制传播而不至于被误认为真章; 早期版本内嵌一张 938×938 的红圈「中」字 PNG,既没有这行声明,也不像章。

与真实印章样例的差异:真实印章的 esID、SES_Header.VID、Property.Name 和证书来自厂商/CA,SES_ESPictrueInfo.Data 是真实印章图片;本演示器用固定的 厂商/项目标识和 internal/sealimg 渲染的测试图代替,其余字段类型与顺序保持一致。

让印章显示在页面上

阅读器只会在 Signature.xml 含 StampAnnot 时把 SES_ESPictrueInfo 图片绘制到页面。 pkg/sign 默认不写 StampAnnot(只验签),需要显示印章时用 --sign-stamp:

go run ./cmd/ofd-creator merge -o /tmp/signed.ofd --pages 1 \
  --sign-cmd /tmp/ofd-signer-demo --sign-stamp --verify-signatures testdata/ofd-creator/hello.ofd

用法

go build -o /tmp/ofd-signer-demo ./cmd/ofd-signer-demo
go run ./cmd/ofd-creator merge \
  -o /tmp/signed.ofd --pages 1 \
  --sign-cmd /tmp/ofd-signer-demo \
  --sign-provider "OFD Signer Demo" \
  --sign-provider-version 0.1.0 \
  --sign-company "OFD Signer Demo" \
  --verify-signatures \
  testdata/ofd-creator/hello.ofd

预期输出:

ofd-creator merge: 签名 sign-1:摘要有效,密码学签名有效

退出码

退出码 含义
0 成功写出 SignedValue.dat;--version、--help 也返回 0
1 失败:未知参数、读取标准输入失败或写出标准输出失败

注意它不校验输入:Signature.xml 的字节只参与 SM3 摘要计算(TBS_Sign.DataHash 就是这段输入的摘要),不做 XML 解析。因此喂进一段垃圾文本同样返回 0 并写出 一个结构完整、但 DataHash 与任何真实签名文件都不对应的 SignedValue.dat。输入 是否合法由 ofd-creator 侧与验签方负责,演示器只演示协议与编码。错误信息写标准错误, SignedValue.dat 只写标准输出,不混在一起。

限制

新增 --digital,或环境变量 OFD_SIGN_TYPE=Sign,可输出 GB/T 35275 的普通 SM2/SM3 SignedData。ofd-creator --sign-type Sign 会传递该环境变量;此时不创建 SES 印章。 普通签名模式仍使用现场生成的自签名证书,不提供生产信任证据或时间戳服务。 可配合 ofd-creator sign --append --sign-cmd ./ofd-signer-demo 演示连续签署; 最后一次使用 --lock-signatures 固定列表,用法见 签署命令。 完整性清单要求带时间戳,该演示器不能直接充当其生产签名器。

这是演示程序,不能用于生产:

  • 证书是每次运行随机生成的自签名证书,没有信任链,重新运行会得到不同的证书和签名;
  • 印章图片是 internal/sealimg 渲染的测试图(顶部「OFD 测试专用章」、底部「非正式印章」),不是有效签章;
  • 私钥不落盘、不持久化,验证方无法确认印章归属;
  • --signatures drop 后重签的文档只用于演示 pkg/creator/merge 与 pkg/sign 的链路。

生产签名器需要接入受信任的证书、密钥管理(HSM/软证书)、时间戳与吊销信息, 并按 Signature.xml 中声明的 SignatureMethod/References@CheckMethod 选择算法。

Documentation

Overview

Command ofd-signer-demo 是 github.com/zc310/ofd 提供的演示签名器, 用于演示 ofd-creator merge --sign-cmd 协议与 SES 结构。

它从标准输入读取 ofd-creator 生成的 Signature.xml,用内存中的 SM2 自签名 证书分别签署 SES 印章信息和外层 TBS_Sign,向标准输出写出 SignedValue.dat。 证书、私钥和印章图片都在进程内生成,仅用于演示与测试,不能用于生产环境, 也不会建立可验证的信任链。

实际的 SES 数据结构与组装逻辑在 internal/ses 包中;本程序只提供参数化的 演示封装,并复用内嵌的占位印章图片。

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL