moon_digest_fields

    RFC 9530 SHA-256/SHA-512 digest generation, HTTP header integration, negotiation, verification, and audit

    http
    digest
    rfc9530
    integrity
    Download zip
    Author
    Version
    0.2.0
    License
    Apache-2.0
    Last updated
    last month
    Downloads
    30

    #Moon Digest Fields

    CI

    MoonBit 实现的 RFC 9530 HTTP Digest Fields 工具库,用于生成、解析和验证 Content-Digest、Repr-Digest、Want-Content-Digest 与 Want-Repr-Digest。它面向下载网关、API 响应校验、代理审计和消息签名流水线, 把“字段是否能解析”和“消息体是否真的匹配”分成可观察的结果。0.2.0 可直接接收 框架无关的 HTTP 头与正文,不要求下游自行拼装字段。

    #核心能力

    • 严格解析 RFC 9530 所用 Structured Fields 字典子集,拒绝重复算法、非法 Base64、越界权重和尾随逗号;
    • 对字段成员排序并生成稳定表示;
    • 一次性或分块计算二进制安全的 SHA-256 与 SHA-512,可生成双算法字段;
    • 以大小写不敏感方式读取 HTTP 头、合并重复字段行并设置/替换摘要头;
    • 从 Want-Content-Digest/Want-Repr-Digest 直接协商服务端算法;
    • 区分匹配、篡改、字段无效、算法不支持、策略阻止、字段缺失和正文超限;
    • 按客户端权重和服务端优先级协商算法;
    • 批量审计捕获的 HTTP 记录,单条坏数据不会中断整批处理;
    • 在 wasm、wasm-gc、JavaScript、native 四个目标上执行 CI。

    #快速开始

    moon add HaQiLyner/moon_digest_fields@0.2.0

    let body = @base64.str2bytes("{\"hello\": \"world\"}\n")
    let response = @digest.apply_digest_header(
    { headers: [{ name: "Content-Type", value: "application/json" }], body },
    @digest.Content,
    )
    let result = @digest.verify_http_message(response, @digest.Content)
    println(result.verification.decision.to_string()) // verified

    moon update moon test --target js moon run cmd/main --target js moon run examples/bench --target js

    #验收边界

    0.2.0 的验收范围是:四类字段的严格解析/稳定输出、SHA-256/SHA-512 生成与 分块计算、HTTP 头接入、验证策略、算法协商、批量审计、RFC/NIST 已知向量、 篡改用例、2500 条 HTTP 集成场景和 20000 次双摘要吞吐工作负载。明确不包含 HTTP 传输栈、TLS、HTTP Message Signatures、内容编码解压或媒体格式规范化。调用方必须把正确的 内容(Content)或选定表示(Representation)字节交给库。

    #测试与实际场景

    http_scenario_test.mbt 通过 HTTP 适配层处理 2500 条响应:2000 条通过、250 条正文被改动、125 条字段损坏、125 条字段缺失。examples/bench 对完整的 HTTP 头查找、双字段解析、SHA-256/SHA-512 与比较路径执行 20000 次。测量方法见 场景验证。

    #文档

    #许可证

    Apache-2.0。依赖与改编来源说明见 docs/provenance.md。

    DigestFieldError

    pub(all) suberror DigestFieldError {
    Syntax(String, Int)
    Policy(String, Int)
    State(String)
    } derive(Eq,
    Debug
    )

    Stable syntax or policy failure. Offsets are zero-based UTF-16 positions in the original field value. Error values never echo the full input.

    AlgorithmStatus

    pub(all) enum AlgorithmStatus {
    Active
    Deprecated
    Unknown
    } derive(Eq,
    Debug
    )

    AuditEntry

    pub(all) struct AuditEntry {
    record_id : String
    target : IntegrityTarget
    field_value : String?
    body : Bytes
    } derive(Eq,
    Debug
    )

    AuditFinding

    pub(all) struct AuditFinding {
    record_id : String
    target : IntegrityTarget
    decision : VerificationDecision
    algorithm : String
    code : String
    } derive(Eq,
    Debug
    )

    AuditReport

    pub(all) struct AuditReport {
    findings : Array[AuditFinding]
    verified : Int
    mismatch : Int
    invalid : Int
    missing : Int
    blocked : Int
    too_large : Int
    } derive(Eq,
    Debug
    )

    DigestField

    pub(all) struct DigestField {
    members : Array[DigestMember]
    } derive(Eq,
    Debug
    )

    DigestField::get

    fn DigestField::get(self : DigestField, algorithm : String) -> Bytes?

    DigestField::to_string

    fn DigestField::to_string(self : DigestField) -> String

    DigestMember

    pub(all) struct DigestMember {
    algorithm : String
    value : Bytes
    } derive(Eq,
    Debug
    )

    HttpHeader

    pub(all) struct HttpHeader {
    name : String
    value : String
    } derive(Eq,
    Debug
    )

    HttpIntegrityResult

    pub(all) struct HttpIntegrityResult {
    field_name : String
    combined_value : String
    occurrences : Int
    verification : Verification
    } derive(Eq,
    Debug
    )

    HttpMessage

    pub(all) struct HttpMessage {
    headers : Array[HttpHeader]
    body : Bytes
    } derive(Eq,
    Debug
    )

    IntegrityTarget

    pub(all) enum IntegrityTarget {
    Content
    Representation
    } derive(Eq,
    Debug
    )

    NegotiationResult

    pub(all) struct NegotiationResult {
    algorithm : String?
    acceptable : Int
    unsupported : Int
    prohibited : Int
    } derive(Eq,
    Debug
    )

    Preference

    pub(all) struct Preference {
    algorithm : String
    weight : Int
    } derive(Eq,
    Debug
    )

    PreferenceField

    pub(all) struct PreferenceField {
    members : Array[Preference]
    } derive(Eq,
    Debug
    )

    PreferenceField::to_string

    fn PreferenceField::to_string(self : PreferenceField) -> String

    Sha256Stream

    pub(all) struct Sha256Stream {
    inner :
    Digest

    bytes_written : Int
    finalized : Bool
    }

    Incremental SHA-256 calculator for HTTP message content.

    Sha256Stream::finish

    fn Sha256Stream::finish(self : Sha256Stream) -> Bytes raise DigestFieldError

    Finalize and return the raw 32-byte SHA-256 digest.

    Sha256Stream::new

    Sha256Stream::update

    fn Sha256Stream::update(self : Sha256Stream, chunk : Bytes) -> Unit raise DigestFieldError

    Add the next body chunk. Updating a finalized stream is rejected.

    Sha512Stream

    pub(all) struct Sha512Stream {
    inner :
    Sha512

    bytes_written : Int
    finalized : Bool
    }

    Incremental binary-safe SHA-512 calculator.

    Sha512Stream::finish

    fn Sha512Stream::finish(self : Sha512Stream) -> Bytes raise DigestFieldError

    Finalize and convert eight big-endian words to the RFC byte sequence.

    Sha512Stream::new

    Sha512Stream::update

    fn Sha512Stream::update(self : Sha512Stream, chunk : Bytes) -> Unit raise DigestFieldError

    Add a body chunk without dropping embedded zero bytes.

    Verification

    pub(all) struct Verification {
    target : IntegrityTarget
    decision : VerificationDecision
    algorithm : String
    code : String
    checked : Int
    ignored : Int
    } derive(Eq,
    Debug
    )

    VerificationDecision

    pub(all) enum VerificationDecision {
    Verified
    Mismatch
    NoSupportedAlgorithm
    PolicyBlocked
    BodyTooLarge
    MissingField
    InvalidField
    } derive(Eq,
    Debug
    )

    VerificationDecision::to_string

    fn VerificationDecision::to_string(self : VerificationDecision) -> String

    VerificationPolicy

    pub(all) struct VerificationPolicy {
    allowed_algorithms : Array[String]
    reject_deprecated : Bool
    require_all_supported : Bool
    max_body_bytes : Int
    max_field_members : Int
    } derive(Eq,
    Debug
    )

    VerificationPolicy::default

    algorithm_status

    fn algorithm_status(algorithm : String) -> AlgorithmStatus

    apply_digest_header

    fn apply_digest_header(message : HttpMessage, target : IntegrityTarget, algorithms? : Array[String]) -> HttpMessage raise DigestFieldError

    Generate and set Content-Digest or Repr-Digest, replacing field lines with the same case-insensitive name while preserving all unrelated headers.

    audit_entries

    fn audit_entries(entries : Array[AuditEntry], policy : VerificationPolicy) -> AuditReport

    Verify many captured HTTP records without aborting the batch on bad input.

    canonicalize_digest_field

    fn canonicalize_digest_field(input : String) -> String raise DigestFieldError

    canonicalize_preference_field

    fn canonicalize_preference_field(input : String) -> String raise DigestFieldError

    content_digest_sha256

    fn content_digest_sha256(input : Bytes) -> String raise DigestFieldError

    Produce the field value used by Content-Digest or Repr-Digest.

    content_digest_sha512

    fn content_digest_sha512(input : Bytes) -> String raise DigestFieldError

    Produce a sha-512 field value.

    digest_field_for

    fn digest_field_for(input : Bytes, algorithms : Array[String]) -> DigestField raise DigestFieldError

    Generate a multi-algorithm field in canonical order.

    negotiate_digest_algorithm

    fn negotiate_digest_algorithm(preferences : PreferenceField, supported : Array[String]) -> NegotiationResult

    Select the supported algorithm with the greatest non-zero client weight. Server preference order breaks ties.

    negotiate_http_digest

    fn negotiate_http_digest(headers : Array[HttpHeader], target : IntegrityTarget, supported? : Array[String]) -> NegotiationResult raise DigestFieldError

    Parse Want-Content-Digest or Want-Repr-Digest headers and choose an algorithm. Repeated field lines are combined before parsing.

    parse_digest_field

    fn parse_digest_field(input : String) -> DigestField raise DigestFieldError

    Parse an RFC 9530 Content-Digest or Repr-Digest value. This release uses a strict Structured Fields subset: dictionary members must be explicit byte sequences and parameters are rejected rather than silently ignored.

    parse_preference_field

    fn parse_preference_field(input : String) -> PreferenceField raise DigestFieldError

    Parse Want-Content-Digest or Want-Repr-Digest. Weights are restricted to RFC 9530's inclusive 0..10 range.

    sha256

    fn sha256(input : Bytes) -> Bytes raise DigestFieldError

    Compute SHA-256 for one byte string.

    sha256_digest_field

    fn sha256_digest_field(input : Bytes) -> DigestField raise DigestFieldError

    Build a one-member DigestField using the active sha-256 algorithm.

    sha256_utf8

    fn sha256_utf8(input : String) -> Bytes raise DigestFieldError

    Compute SHA-256 over the UTF-8 bytes of a string.

    sha512

    fn sha512(input : Bytes) -> Bytes raise DigestFieldError

    Compute binary-safe SHA-512.

    sha512_digest_field

    fn sha512_digest_field(input : Bytes) -> DigestField raise DigestFieldError

    Build a one-member DigestField using sha-512.

    sha512_utf8

    fn sha512_utf8(input : String) -> Bytes raise DigestFieldError

    Compute SHA-512 over UTF-8 string bytes.

    verify_digest

    fn verify_digest(target : IntegrityTarget, field : DigestField, body : Bytes, policy : VerificationPolicy) -> Verification

    Verify a parsed Content-Digest or Repr-Digest value against body bytes.

    verify_digest_field

    fn verify_digest_field(target : IntegrityTarget, field_value : String, body : Bytes, policy : VerificationPolicy) -> Verification

    Parse and verify a wire-format field value.

    verify_http_message

    fn verify_http_message(message : HttpMessage, target : IntegrityTarget, policy? : VerificationPolicy) -> HttpIntegrityResult

    Verify digest headers from an HTTP adapter without depending on a specific server framework. Repeated field lines are combined in wire order.