You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
DateKeys/provider/provider.go

116 lines
5.1 KiB

// Package provider defines conditions, releases and release sources (spec §9,
// §45-§52) and the local verification every release must pass.
//
// A release is never trusted because of where it came from: the DateKeys API,
// a cache or a relay are untrusted transports (spec §3, §48, §52). A remote
// "verified: true" has no security value (spec §51).
package provider
import (
Release object, release in hand and step 9.c option B (spec v0.15 draft) The release of a round becomes a file, .dkr: a release object in deterministic CBOR, {0: "datekeys-release", 1: 1, 2: chain_hash, 3: round, 4: signature}, which provider.EncodeRelease writes and DecodeRelease reads with its layers (size, type and version, schema). provider.ParseRelease also reads drand's JSON as the input of the caller. Verify checks the chain hash a release names before its round and its signature, with ERR_PROFILE_MISMATCH. provider.Archive reads a local release archive, the informative format of the draft. capsule.OpenOptions.Release takes a release in hand, a provider.Supplier, exclusive with Source: Open does not compare it with the clock (step 9.c, option B) and reports a clock behind it in Opened.ClockBehind; a network source is still never asked before the round time. The CLI gains decrypt -release FILE (.dkr, drand's JSON or a local archive), decrypt -save-release FILE.dkr and the command release, which fetches, verifies and saves the .dkr without opening the capsule. Test data: vectors/release.json, releases/<round>.dkr for rounds 1000, 1001, 1004 and 2000, and a local archive of rounds 1000 to 1004. In mutations.json every case says its source, "supplied" or "network"; the case "round not reached yet", a release in hand, now opens, and four cases are added: the same with a network source, a release of another round from a network source, and two release objects of another chain. SpecVersion stays 0.14 until the author approves the draft. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2 days ago
"bytes"
"context"
Release object, release in hand and step 9.c option B (spec v0.15 draft) The release of a round becomes a file, .dkr: a release object in deterministic CBOR, {0: "datekeys-release", 1: 1, 2: chain_hash, 3: round, 4: signature}, which provider.EncodeRelease writes and DecodeRelease reads with its layers (size, type and version, schema). provider.ParseRelease also reads drand's JSON as the input of the caller. Verify checks the chain hash a release names before its round and its signature, with ERR_PROFILE_MISMATCH. provider.Archive reads a local release archive, the informative format of the draft. capsule.OpenOptions.Release takes a release in hand, a provider.Supplier, exclusive with Source: Open does not compare it with the clock (step 9.c, option B) and reports a clock behind it in Opened.ClockBehind; a network source is still never asked before the round time. The CLI gains decrypt -release FILE (.dkr, drand's JSON or a local archive), decrypt -save-release FILE.dkr and the command release, which fetches, verifies and saves the .dkr without opening the capsule. Test data: vectors/release.json, releases/<round>.dkr for rounds 1000, 1001, 1004 and 2000, and a local archive of rounds 1000 to 1004. In mutations.json every case says its source, "supplied" or "network"; the case "round not reached yet", a release in hand, now opens, and four cases are added: the same with a network source, a release of another round from a network source, and two release objects of another chain. SpecVersion stays 0.14 until the author approves the draft. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2 days ago
"crypto/sha256"
"encoding/hex"
"fmt"
Release object, release in hand and step 9.c option B (spec v0.15 draft) The release of a round becomes a file, .dkr: a release object in deterministic CBOR, {0: "datekeys-release", 1: 1, 2: chain_hash, 3: round, 4: signature}, which provider.EncodeRelease writes and DecodeRelease reads with its layers (size, type and version, schema). provider.ParseRelease also reads drand's JSON as the input of the caller. Verify checks the chain hash a release names before its round and its signature, with ERR_PROFILE_MISMATCH. provider.Archive reads a local release archive, the informative format of the draft. capsule.OpenOptions.Release takes a release in hand, a provider.Supplier, exclusive with Source: Open does not compare it with the clock (step 9.c, option B) and reports a clock behind it in Opened.ClockBehind; a network source is still never asked before the round time. The CLI gains decrypt -release FILE (.dkr, drand's JSON or a local archive), decrypt -save-release FILE.dkr and the command release, which fetches, verifies and saves the .dkr without opening the capsule. Test data: vectors/release.json, releases/<round>.dkr for rounds 1000, 1001, 1004 and 2000, and a local archive of rounds 1000 to 1004. In mutations.json every case says its source, "supplied" or "network"; the case "round not reached yet", a release in hand, now opens, and four cases are added: the same with a network source, a release of another round from a network source, and two release objects of another chain. SpecVersion stays 0.14 until the author approves the draft. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2 days ago
"strings"
"github.com/drand/drand/v2/common"
datekeys "g.activething.com/go/DateKeys"
"g.activething.com/go/DateKeys/profile"
)
// Condition is the time condition of a Quicknet-style profile: a round.
type Condition struct {
Round uint64
}
// Release is the material that satisfies a condition. For drand it is the
// BLS signature of the round.
type Release struct {
Round uint64
Signature []byte
Release object, release in hand and step 9.c option B (spec v0.15 draft) The release of a round becomes a file, .dkr: a release object in deterministic CBOR, {0: "datekeys-release", 1: 1, 2: chain_hash, 3: round, 4: signature}, which provider.EncodeRelease writes and DecodeRelease reads with its layers (size, type and version, schema). provider.ParseRelease also reads drand's JSON as the input of the caller. Verify checks the chain hash a release names before its round and its signature, with ERR_PROFILE_MISMATCH. provider.Archive reads a local release archive, the informative format of the draft. capsule.OpenOptions.Release takes a release in hand, a provider.Supplier, exclusive with Source: Open does not compare it with the clock (step 9.c, option B) and reports a clock behind it in Opened.ClockBehind; a network source is still never asked before the round time. The CLI gains decrypt -release FILE (.dkr, drand's JSON or a local archive), decrypt -save-release FILE.dkr and the command release, which fetches, verifies and saves the .dkr without opening the capsule. Test data: vectors/release.json, releases/<round>.dkr for rounds 1000, 1001, 1004 and 2000, and a local archive of rounds 1000 to 1004. In mutations.json every case says its source, "supplied" or "network"; the case "round not reached yet", a release in hand, now opens, and four cases are added: the same with a network source, a release of another round from a network source, and two release objects of another chain. SpecVersion stays 0.14 until the author approves the draft. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2 days ago
// ChainHash is the chain the release names, key 2 of a release object
// (spec v0.15, §47.1), or nil when it names none, as the answer of a
// relay and drand's JSON. Verify compares it with the pinned profile.
ChainHash []byte
}
Spec v0.8.2: corrections from the formal review A formal review of the whole v0.8.2 text found it approvable after these corrections, recorded in §76 ("Correcciones de la revisión formal"): - §27 no longer calls header_binding the authenticity of PUBLIC_HEADER: it binds the header to the opened control, never authorship or date (§55.1); the age MAC only protects against whoever lacks the file key. - §63 steps 9 and 10: a network source (relay, Release API, cache) MUST verify every response and gives ERR_RELEASE_UNAVAILABLE at step 9 when none verifies; the step-10 codes are for a directly supplied release. The reference already behaved so; TestReleaseFromANetworkSource pins both paths. - §54 and §72: registrations declare the objects and arrays where an extension may appear, and a known extension out of place counts as unknown there. The reference gains the optional extension.Placement interface, used at steps 4, 9.a and 14. - §63 step 11 fixes the GT serialization hashed by H2 (kilic/kyber order) with the frozen vector H2(e(G1, G2))[:16] = cb87319f..., shared as testdata/vectors/tlock_ibe.json; H2-H4 are cited to drand/kyber. - Step 5 makes the SEALED_CONTROL read mandatory, step 15 names ERR_HEADER_BINDING, §21 makes capsule_id 16 CSPRNG bytes a MUST, §76 is made accurate (four dk1.json vectors, the §36 time_only rule, two cases rewritten against the texts that really existed), and editorial fixes in §5, §36, §55.1, §69.1 and §77. §73 lists the three new decisions. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2 weeks ago
// ReleaseSource fetches the release of a condition. Callers always verify the
// release, with Verify (spec §63 step 10).
//
// A source that fetches releases over a network (a relay, the Release API or
// a cache) must also verify each response with Verify and discard the one
// that fails, and report datekeys.ErrReleaseUnavailable when no response
// passes (spec §63 step 9), as provider/drand.Client does: an invalid release
// from the network is then reported at step 9, not with the codes of step 10.
// A source that hands over a release the caller supplies directly need not
// verify it; its release gets the codes of step 10.
//
Spec v0.8.2: second-round corrections from the formal review The second round of the formal review confirmed the nine corrections of c57ed48 and asked for these, recorded in §76 as corrections 4 to 6 and an editorial note: - §72: an encoder MUST NOT write a registered extension in an object or array it is not registered for; §54: a reader MUST NOT interpret the data of a noncritical one it ignores for that reason. capsule.Encrypt and accesskey.Encode take no Registry, so the application applies the rule; their documentation and extension.Placement say so. - §17 and §51 give the step-10 codes only for a directly supplied release, as step 10 does; a network source discards a failing one at step 9. - Step 9 reports ERR_RELEASE_UNAVAILABLE and no other code, whatever the failure of the source. provider/drand.Client keeps each relay's failure as text only (errors.Join made a relay's ERR_ROUND_MISMATCH match with errors.Is), and capsule.Open keeps only the text of a source error that carries another code (a caller's source failing with ERR_RELEASE_INVALID gave that code at step 9). A context that ended stays detectable: Fetch now has a single failure path, so the canceled and deadline cases are deterministic. - TestExtensionPlacement covers the noncritical array of a .dkk: with the object-blind extension.CheckNoncritical at step 9.a it fails. - Editorial: §28.1 "analizan solo la cabecera age", one arrow at step 9, two §76 introductions; §73 lines for release sources and placement. - testdata/README.md says the corpus registers its extensions in both arrays of every object; traceability, CHANGELOG and both READMEs (integrity holds against whoever lacks the file keys, §27, §55.1) follow. Spec dated 28 September 2026; new SHA-256 in spec/README.md. No fixture or vector changes. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2 weeks ago
// Errors should wrap datekeys.ErrReleaseUnavailable, and no other normative
// error, when the release cannot be obtained, for example because the round
// is not published yet. capsule.Open reports any error of a source at step 9
// with ErrReleaseUnavailable as its only code, the one spec §63 gives that
// step, and keeps only the text of an error that carries another code.
type ReleaseSource interface {
Fetch(ctx context.Context, p *profile.Profile, c Condition) (Release, error)
}
// ReleaseSourceFunc adapts a function to ReleaseSource.
type ReleaseSourceFunc func(ctx context.Context, p *profile.Profile, c Condition) (Release, error)
// Fetch calls f.
func (f ReleaseSourceFunc) Fetch(ctx context.Context, p *profile.Profile, c Condition) (Release, error) {
return f(ctx, p, c)
}
Spec v0.8.2 refinements: error precedence, trust model, strict order Approved refinements, each recorded with its reproducible case in the §76 v0.8.2 subsection: - §69.1: layered error model with normative precedence (frame, type tag and version, CBOR profile and CDDL, then fields with their own code in ascending key order; across steps the §63 order decides), with a scope paragraph for the optional steps 5, 6 and 8. - §55.1: normative trust table per section (who can write it, from which step it is bound, what it never proves); §72: security-relevant claims go in CONTROL_CBOR or under a signature, .dkk data is advisory. - §31/§54: extension arrays in strictly ascending unsigned byte order of extension_id (one rule for order and uniqueness). - Gaps a second implementation needed: §28.1 malformed age headers, §15/§19 latest unlock time and dk1_ reading rules, §22/§23/§57 length lower bounds, §63 step 8 tlock argument comparison and step 9 order, §12.1 profile validation with the drand chain-hash formula, §74 table of implementation limits. Reference alignment: .dkk errors only at step 9.a (new OpenOptions.AccessKeyFile, used by the CLI), CR/LF in dk1_ is ERR_DATEKEY_INVALID, BODY_LEN 0 is ERR_INTEGRITY, nil identities are not credentials, and AccessIdentity tries every identity on every stanza so its verdict does not depend on their order. dk1.json gains three vectors; every other testdata file is byte-identical. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2 weeks ago
// Verify checks a release locally against the pinned profile (spec §17, §51),
Release object, release in hand and step 9.c option B (spec v0.15 draft) The release of a round becomes a file, .dkr: a release object in deterministic CBOR, {0: "datekeys-release", 1: 1, 2: chain_hash, 3: round, 4: signature}, which provider.EncodeRelease writes and DecodeRelease reads with its layers (size, type and version, schema). provider.ParseRelease also reads drand's JSON as the input of the caller. Verify checks the chain hash a release names before its round and its signature, with ERR_PROFILE_MISMATCH. provider.Archive reads a local release archive, the informative format of the draft. capsule.OpenOptions.Release takes a release in hand, a provider.Supplier, exclusive with Source: Open does not compare it with the clock (step 9.c, option B) and reports a clock behind it in Opened.ClockBehind; a network source is still never asked before the round time. The CLI gains decrypt -release FILE (.dkr, drand's JSON or a local archive), decrypt -save-release FILE.dkr and the command release, which fetches, verifies and saves the .dkr without opening the capsule. Test data: vectors/release.json, releases/<round>.dkr for rounds 1000, 1001, 1004 and 2000, and a local archive of rounds 1000 to 1004. In mutations.json every case says its source, "supplied" or "network"; the case "round not reached yet", a release in hand, now opens, and four cases are added: the same with a network source, a release of another round from a network source, and two release objects of another chain. SpecVersion stays 0.14 until the author approves the draft. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2 days ago
// in the order of spec §63 step 10: the chain hash it names, if any, which
// must be that of the pinned profile (ErrProfileMismatch, spec v0.15); the
// expected round (ErrRoundMismatch),
Spec v0.8.2 amendment: canonical point encoding; no library error text Amendment of the unreleased v0.8.2, recorded in §76 with its case: the second implementation's phase-2 research found that tlock-js over @noble/curves 1.9.7 accepts U re-encoded as c0 + p and a signature x + p and returns the same file key, while the reference rejects both (noble 1.9.7 differed from kilic on 5,615 of 41,686 encodings), and the spec did not say which encodings are valid. - §12.2 defines the canonical encoding of a BLS12-381 point (drand's compressed ZCash form) and requires decoders to reject every other byte string; §12.1 applies it to public_key. - §63 step 10 applies it to the release signature (ERR_RELEASE_INVALID) and step 11 defines the tlock stanza body U || V || W (96 + 16 + 16 bytes for Quicknet) with a canonical, non-infinity U (ERR_INTEGRITY). - §64 gains ten mutations, exported to mutations.json (65 cases). The signature x + p case uses published Quicknet round 1004, the first after 1000 whose x allows x + p < 2^381. The reference already gave every stated code and step. Errors no longer copy text from tlock, kyber, age, drand or kyber-bls12381. kyber's IBE error carried the candidate plaintext and r, and with one bit of W flipped the message disclosed the real tlock file key with that bit flipped. Every such place now uses a fixed reason with its normative sentinel; TestTlockFailureDiagnosticsCarryNoSecrets fails with the old wrapping. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2 weeks ago
// then the signature (ErrReleaseInvalid), which must be the canonical
// encoding of a point of the signature group of the scheme other than the
// point at infinity (spec §12.2), with the length of that group, and a valid
// BLS signature of the round under the pinned public key. The chain hash is
Release object, release in hand and step 9.c option B (spec v0.15 draft) The release of a round becomes a file, .dkr: a release object in deterministic CBOR, {0: "datekeys-release", 1: 1, 2: chain_hash, 3: round, 4: signature}, which provider.EncodeRelease writes and DecodeRelease reads with its layers (size, type and version, schema). provider.ParseRelease also reads drand's JSON as the input of the caller. Verify checks the chain hash a release names before its round and its signature, with ERR_PROFILE_MISMATCH. provider.Archive reads a local release archive, the informative format of the draft. capsule.OpenOptions.Release takes a release in hand, a provider.Supplier, exclusive with Source: Open does not compare it with the clock (step 9.c, option B) and reports a clock behind it in Opened.ClockBehind; a network source is still never asked before the round time. The CLI gains decrypt -release FILE (.dkr, drand's JSON or a local archive), decrypt -save-release FILE.dkr and the command release, which fetches, verifies and saves the .dkr without opening the capsule. Test data: vectors/release.json, releases/<round>.dkr for rounds 1000, 1001, 1004 and 2000, and a local archive of rounds 1000 to 1004. In mutations.json every case says its source, "supplied" or "network"; the case "round not reached yet", a release in hand, now opens, and four cases are added: the same with a network source, a release of another round from a network source, and two release objects of another chain. SpecVersion stays 0.14 until the author approves the draft. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2 days ago
// covered too because the pinned public key is bound to it by
// profile.Validate.
Spec v0.8.2 amendment: canonical point encoding; no library error text Amendment of the unreleased v0.8.2, recorded in §76 with its case: the second implementation's phase-2 research found that tlock-js over @noble/curves 1.9.7 accepts U re-encoded as c0 + p and a signature x + p and returns the same file key, while the reference rejects both (noble 1.9.7 differed from kilic on 5,615 of 41,686 encodings), and the spec did not say which encodings are valid. - §12.2 defines the canonical encoding of a BLS12-381 point (drand's compressed ZCash form) and requires decoders to reject every other byte string; §12.1 applies it to public_key. - §63 step 10 applies it to the release signature (ERR_RELEASE_INVALID) and step 11 defines the tlock stanza body U || V || W (96 + 16 + 16 bytes for Quicknet) with a canonical, non-infinity U (ERR_INTEGRITY). - §64 gains ten mutations, exported to mutations.json (65 cases). The signature x + p case uses published Quicknet round 1004, the first after 1000 whose x allows x + p < 2^381. The reference already gave every stated code and step. Errors no longer copy text from tlock, kyber, age, drand or kyber-bls12381. kyber's IBE error carried the candidate plaintext and r, and with one bit of W flipped the message disclosed the real tlock file key with that bit flipped. Every such place now uses a fixed reason with its normative sentinel; TestTlockFailureDiagnosticsCarryNoSecrets fails with the old wrapping. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2 weeks ago
//
// The BLS verification of drand decodes the signature with the canonical
// decoder of kilic/bls12-381, which rejects every other encoding, and the
// point at infinity never verifies because the pinned public key is not the
// point at infinity. The error of drand is not copied.
func Verify(p *profile.Profile, c Condition, r Release) error {
if c.Round == 0 || c.Round > p.MaxRound() {
return fmt.Errorf("provider: round %d outside the range of %s: %w", c.Round, p.ID, datekeys.ErrDateKeyInvalid)
}
Release object, release in hand and step 9.c option B (spec v0.15 draft) The release of a round becomes a file, .dkr: a release object in deterministic CBOR, {0: "datekeys-release", 1: 1, 2: chain_hash, 3: round, 4: signature}, which provider.EncodeRelease writes and DecodeRelease reads with its layers (size, type and version, schema). provider.ParseRelease also reads drand's JSON as the input of the caller. Verify checks the chain hash a release names before its round and its signature, with ERR_PROFILE_MISMATCH. provider.Archive reads a local release archive, the informative format of the draft. capsule.OpenOptions.Release takes a release in hand, a provider.Supplier, exclusive with Source: Open does not compare it with the clock (step 9.c, option B) and reports a clock behind it in Opened.ClockBehind; a network source is still never asked before the round time. The CLI gains decrypt -release FILE (.dkr, drand's JSON or a local archive), decrypt -save-release FILE.dkr and the command release, which fetches, verifies and saves the .dkr without opening the capsule. Test data: vectors/release.json, releases/<round>.dkr for rounds 1000, 1001, 1004 and 2000, and a local archive of rounds 1000 to 1004. In mutations.json every case says its source, "supplied" or "network"; the case "round not reached yet", a release in hand, now opens, and four cases are added: the same with a network source, a release of another round from a network source, and two release objects of another chain. SpecVersion stays 0.14 until the author approves the draft. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2 days ago
if r.ChainHash != nil && !bytes.Equal(r.ChainHash, p.ChainHash[:]) {
return fmt.Errorf("provider: release of chain %s, the pinned profile %s is chain %s: %w", chainHashHex(r.ChainHash), p.ID, p.ChainHashHex(), datekeys.ErrProfileMismatch)
}
if r.Round != c.Round {
return fmt.Errorf("provider: release for round %d, expected %d: %w", r.Round, c.Round, datekeys.ErrRoundMismatch)
}
scheme, err := p.DrandScheme()
if err != nil {
return err
}
if want := scheme.SigGroup.PointLen(); len(r.Signature) != want {
return fmt.Errorf("provider: signature is %d bytes, %s uses %d: %w", len(r.Signature), scheme.Name, want, datekeys.ErrReleaseInvalid)
}
key := scheme.KeyGroup.Point()
if err := key.UnmarshalBinary(p.PublicKey); err != nil {
Spec v0.8.2 amendment: canonical point encoding; no library error text Amendment of the unreleased v0.8.2, recorded in §76 with its case: the second implementation's phase-2 research found that tlock-js over @noble/curves 1.9.7 accepts U re-encoded as c0 + p and a signature x + p and returns the same file key, while the reference rejects both (noble 1.9.7 differed from kilic on 5,615 of 41,686 encodings), and the spec did not say which encodings are valid. - §12.2 defines the canonical encoding of a BLS12-381 point (drand's compressed ZCash form) and requires decoders to reject every other byte string; §12.1 applies it to public_key. - §63 step 10 applies it to the release signature (ERR_RELEASE_INVALID) and step 11 defines the tlock stanza body U || V || W (96 + 16 + 16 bytes for Quicknet) with a canonical, non-infinity U (ERR_INTEGRITY). - §64 gains ten mutations, exported to mutations.json (65 cases). The signature x + p case uses published Quicknet round 1004, the first after 1000 whose x allows x + p < 2^381. The reference already gave every stated code and step. Errors no longer copy text from tlock, kyber, age, drand or kyber-bls12381. kyber's IBE error carried the candidate plaintext and r, and with one bit of W flipped the message disclosed the real tlock file key with that bit flipped. Every such place now uses a fixed reason with its normative sentinel; TestTlockFailureDiagnosticsCarryNoSecrets fails with the old wrapping. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2 weeks ago
return fmt.Errorf("provider: pinned public key of %s is not the canonical encoding of a point of the key group: %w", p.ID, datekeys.ErrUnknownProfile)
}
beacon := &common.Beacon{Round: r.Round, Signature: r.Signature}
if err := scheme.VerifyBeacon(beacon, key); err != nil {
Spec v0.8.2 amendment: canonical point encoding; no library error text Amendment of the unreleased v0.8.2, recorded in §76 with its case: the second implementation's phase-2 research found that tlock-js over @noble/curves 1.9.7 accepts U re-encoded as c0 + p and a signature x + p and returns the same file key, while the reference rejects both (noble 1.9.7 differed from kilic on 5,615 of 41,686 encodings), and the spec did not say which encodings are valid. - §12.2 defines the canonical encoding of a BLS12-381 point (drand's compressed ZCash form) and requires decoders to reject every other byte string; §12.1 applies it to public_key. - §63 step 10 applies it to the release signature (ERR_RELEASE_INVALID) and step 11 defines the tlock stanza body U || V || W (96 + 16 + 16 bytes for Quicknet) with a canonical, non-infinity U (ERR_INTEGRITY). - §64 gains ten mutations, exported to mutations.json (65 cases). The signature x + p case uses published Quicknet round 1004, the first after 1000 whose x allows x + p < 2^381. The reference already gave every stated code and step. Errors no longer copy text from tlock, kyber, age, drand or kyber-bls12381. kyber's IBE error carried the candidate plaintext and r, and with one bit of W flipped the message disclosed the real tlock file key with that bit flipped. Every such place now uses a fixed reason with its normative sentinel; TestTlockFailureDiagnosticsCarryNoSecrets fails with the old wrapping. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2 weeks ago
return fmt.Errorf("provider: the signature is not a canonical point encoding, or does not verify as the BLS signature of round %d under %s: %w", r.Round, p.ID, datekeys.ErrReleaseInvalid)
}
return nil
}
Release object, release in hand and step 9.c option B (spec v0.15 draft) The release of a round becomes a file, .dkr: a release object in deterministic CBOR, {0: "datekeys-release", 1: 1, 2: chain_hash, 3: round, 4: signature}, which provider.EncodeRelease writes and DecodeRelease reads with its layers (size, type and version, schema). provider.ParseRelease also reads drand's JSON as the input of the caller. Verify checks the chain hash a release names before its round and its signature, with ERR_PROFILE_MISMATCH. provider.Archive reads a local release archive, the informative format of the draft. capsule.OpenOptions.Release takes a release in hand, a provider.Supplier, exclusive with Source: Open does not compare it with the clock (step 9.c, option B) and reports a clock behind it in Opened.ClockBehind; a network source is still never asked before the round time. The CLI gains decrypt -release FILE (.dkr, drand's JSON or a local archive), decrypt -save-release FILE.dkr and the command release, which fetches, verifies and saves the .dkr without opening the capsule. Test data: vectors/release.json, releases/<round>.dkr for rounds 1000, 1001, 1004 and 2000, and a local archive of rounds 1000 to 1004. In mutations.json every case says its source, "supplied" or "network"; the case "round not reached yet", a release in hand, now opens, and four cases are added: the same with a network source, a release of another round from a network source, and two release objects of another chain. SpecVersion stays 0.14 until the author approves the draft. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2 days ago
// randomnessMatches reports whether the randomness of a drand answer, in
// hexadecimal, is SHA-256 of its signature, as drand defines it.
func randomnessMatches(randomness string, signature []byte) bool {
sum := sha256.Sum256(signature)
return strings.EqualFold(randomness, hex.EncodeToString(sum[:]))
}

Powered by TurnKey Linux.