Spec v0.14 draft: what is not guaranteed, the provider, the root of trust

The draft writes down what the completeness review of 6 October 2026 found
missing, and changes no format and no verdict: what the protocol does not
guarantee, the provider and the states of a profile, signatures and seals
against a quantum adversary, the web client, the entropy of a key of words,
and errata of section 76. Steps 10 and 11 of section 63 now give the root
of trust byte for byte, as the three implementations apply it: the message
a Quicknet round signs, its hash to G1 with its DST, and H2, H3 and H4 of
the tlock IBE. testdata/vectors/tlock_steps.json gives every intermediate
value for four published rounds, checked against drand, kyber and tlock.
SpecVersion stays 0.13 until the author approves the draft.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
v0.14
dev 24 hours ago
parent 416c15534c
commit 49b376411e

@ -3,6 +3,26 @@
All notable changes to this module are documented here. The project follows
semantic versioning; `v0.x` versions make no API stability promise.
## Unreleased — specification v0.14 draft
The draft v0.14 of the DateKeys Protocol Specification, on the branch
`v0.14` and not approved yet. It changes no format, no verdict and no code
path: `SpecVersion` stays 0.13 until the author approves the draft.
- **Specification.** `spec/DateKeys_Protocol_Specification_v0.14.md`, whose
§76 lists seven changes with their cases: what the protocol does not
guarantee (§5), the provider and the states of a profile (§7.6, §36.1,
§71), signatures and seals against a quantum adversary (§7.7, §53), the web
client (§7.10, §59), the entropy of a key of words (§38.1), the root of
trust byte for byte (§12, §35, §51, §63 steps 10 and 11), and errata.
- **Test data.** `vectors/tlock_steps.json`, new, from
`internal/testkit.TlockStepVectors`: for the published rounds 1000, 1001,
1004 and 2000, the message a round signs, its hash to G1 and the pairing
equation of step 10; and the decryption of five tlock stanzas in step 11,
with e(signature, U), H2, sigma, H4, the file key, every try of H3 and r.
The generator computes each value with its own H2, H3 and H4 and checks it
against drand, kyber and tlock.
## Unreleased — specification v0.13
Implements the DateKeys Protocol Specification v0.13, which its author

@ -2,7 +2,10 @@
Implementación de referencia en Go de la **DateKeys Protocol Specification
v0.13** ([`spec/`](spec/DateKeys_Protocol_Specification_v0.13.md)), etiquetada
`spec-v0.13`, que no cambia ningún formato de la v0.11 ni de la v0.12.
`spec-v0.13`, que no cambia ningún formato de la v0.11 ni de la v0.12. Esta
rama, `v0.14`, lleva además el borrador v0.14
([`spec/`](spec/DateKeys_Protocol_Specification_v0.14.md)), aún sin aprobar,
que no cambia ningún formato ni ningún veredicto.
[English version](README.md).
DateKeys cifra datos de forma que solo puedan abrirse a partir de un instante

@ -2,7 +2,10 @@
Reference implementation in Go of the **DateKeys Protocol Specification
v0.13** ([`spec/`](spec/DateKeys_Protocol_Specification_v0.13.md)), tagged
`spec-v0.13`, which changes no format of v0.11 or v0.12.
`spec-v0.13`, which changes no format of v0.11 or v0.12. This branch,
`v0.14`, also carries the draft v0.14
([`spec/`](spec/DateKeys_Protocol_Specification_v0.14.md)), not approved yet,
which changes no format and no verdict.
[Versión en español](README.es.md).
DateKeys encrypts data so that it can only be opened after a chosen instant.

@ -7,9 +7,9 @@ reviewer together with the specification, the fixtures and the mutation corpus
(plan §10).
Paths are relative to the repository root. `§` numbers refer to
`spec/DateKeys_Protocol_Specification_v0.13.md`, tagged `spec-v0.13`; v0.12,
tagged `spec-v0.12`, and v0.11, tagged `spec-v0.11`, number their sections
the same. A case of §64 that is not in the repository yet is marked
`spec/DateKeys_Protocol_Specification_v0.14.md`, the draft of the branch
`v0.14`, not approved yet; v0.13, tagged `spec-v0.13`, v0.12 and v0.11
number their sections the same, but for §7.10, new in the draft. A case of §64 that is not in the repository yet is marked
*pending*.
## Section map

@ -195,7 +195,11 @@ func format3Vectors(dir string) error {
if err != nil {
return err
}
for name, v := range map[string]any{"paths.json": paths, "path_fold.json": fold, "head_schema.json": heads, "security.json": security, "ed25519_strict.json": strict, "note.json": note, "wordkey.json": words, "resolved_ip.json": resolved} {
steps, err := testkit.TlockStepVectors()
if err != nil {
return err
}
for name, v := range map[string]any{"paths.json": paths, "path_fold.json": fold, "head_schema.json": heads, "security.json": security, "ed25519_strict.json": strict, "note.json": note, "wordkey.json": words, "resolved_ip.json": resolved, "tlock_steps.json": steps} {
if err := testkit.WriteJSON(filepath.Join(dir, name), v); err != nil {
return err
}

@ -275,6 +275,10 @@ func TestVectorFilesAreCurrent(t *testing.T) {
if err != nil {
t.Fatal(err)
}
steps, err := testkit.TlockStepVectors()
if err != nil {
t.Fatal(err)
}
for _, v := range []struct {
file string
want any
@ -290,6 +294,7 @@ func TestVectorFilesAreCurrent(t *testing.T) {
{"note.json", note, &testkit.NoteVectorFile{}},
{"wordkey.json", words, &testkit.WordKeyVectorFile{}},
{"resolved_ip.json", resolved, &testkit.ResolvedIPVectorFile{}},
{"tlock_steps.json", steps, &testkit.TlockStepsFile{}},
} {
if err := testkit.ReadJSON("../../testdata/vectors/"+v.file, v.got); err != nil {
t.Fatal(err)

@ -0,0 +1,340 @@
package testkit
import (
"bytes"
"crypto/sha256"
"encoding/binary"
"encoding/hex"
"errors"
"fmt"
"math/big"
"slices"
"strconv"
"filippo.io/age"
"github.com/drand/drand/v2/common"
"github.com/drand/drand/v2/crypto"
"github.com/drand/kyber"
bls "github.com/drand/kyber-bls12381"
"github.com/drand/kyber/encrypt/ibe"
"github.com/drand/kyber/pairing"
"github.com/drand/tlock"
"g.activething.com/go/DateKeys/agewrap"
"g.activething.com/go/DateKeys/profile"
"g.activething.com/go/DateKeys/provider"
)
// TlockStepsFile is testdata/vectors/tlock_steps.json: the intermediate
// values of steps 10 and 11 of spec §63 for Quicknet, over published
// releases. Step 10: the message of a round, its hash to G1 and the pairing
// check of the signature. Step 11: the decryption of a tlock stanza, H2, H4,
// the file key and H3 with each of its tries.
type TlockStepsFile struct {
Spec string `json:"spec"`
Description string `json:"description"`
Profile string `json:"profile"`
Scheme string `json:"scheme"`
ChainHash string `json:"chain_hash"`
PublicKey string `json:"public_key"`
DST string `json:"dst"`
Tags TlockStepTags `json:"tags"`
Vectors []TlockStepVector `json:"vectors"`
}
// TlockStepTags are the domain separation tags of H2, H3 and H4, in hex.
type TlockStepTags struct {
H2 string `json:"h2"`
H3 string `json:"h3"`
H4 string `json:"h4"`
}
// TlockStepVector is one round and one stanza of it. Every byte string is
// hex. The writer chose sigma and file_key; the rest follows from them, the
// pinned public key and the signature of the round.
type TlockStepVector struct {
Name string `json:"name"`
Round uint64 `json:"round"`
Signature string `json:"signature"` // the release, compressed G1
Message string `json:"message"` // M = SHA-256(uint64_be(round))
HashToG1 string `json:"hash_to_g1"` // H(M), compressed G1
Body string `json:"body"` // U || V || W, the stanza body
U string `json:"u"` // compressed G2
V string `json:"v"` // 16 bytes
W string `json:"w"` // 16 bytes
Pairing string `json:"pairing"` // e(signature, U), 576 bytes
H2 string `json:"h2"` // H2(pairing), 16 bytes
Sigma string `json:"sigma"` // V XOR H2
H4 string `json:"h4"` // H4(sigma), 16 bytes
FileKey string `json:"file_key"` // W XOR H4: FK_TIME
H3Base string `json:"h3_base"` // SHA-256("IBE-H3" || sigma || file_key)
H3Tries []H3Try `json:"h3_tries"` // the tries of H3, the last one accepted
R string `json:"r"` // H3(sigma, file_key), 32 bytes big-endian
}
// H3Try is one try of H3: the counter i, d = SHA-256(uint16_le(i) ||
// h3_base), d with its first byte shifted one bit to the right, and whether
// that is below the order of the group.
type H3Try struct {
I int `json:"i"`
Digest string `json:"digest"`
Shifted string `json:"shifted"`
Accepted bool `json:"accepted"`
}
// The order of the groups of BLS12-381 (spec §12.2), written out here
// rather than taken from kyber, against which this file checks itself.
var tlockStepOrder, _ = new(big.Int).SetString("73eda753299d7d483339d80809a1d80553bda402fffe5bfeffffffff00000001", 16)
// The tags of H2, H3 and H4 and the DST of Quicknet, written out here.
const (
tlockStepH2Tag = "IBE-H2"
tlockStepH3Tag = "IBE-H3"
tlockStepH4Tag = "IBE-H4"
tlockStepDST = "BLS_SIG_BLS12381G1_XMD:SHA-256_SSWU_RO_NUL_"
)
// tlockStepMessage is the message a Quicknet signature signs.
func tlockStepMessage(round uint64) []byte {
var b [8]byte
binary.BigEndian.PutUint64(b[:], round)
m := sha256.Sum256(b[:])
return m[:]
}
func tlockStepHash(n int, parts ...[]byte) []byte {
h := sha256.New()
for _, p := range parts {
h.Write(p)
}
return h.Sum(nil)[:n]
}
// tlockStepH3 is H3 as spec §63 writes it, independently of kyber.
func tlockStepH3(sigma, fileKey []byte) (base []byte, tries []H3Try, r []byte, err error) {
base = tlockStepHash(32, []byte(tlockStepH3Tag), sigma, fileKey)
for i := 1; i <= 65534; i++ {
d := tlockStepHash(32, []byte{byte(i), byte(i >> 8)}, base)
s := bytes.Clone(d)
s[0] >>= 1
ok := new(big.Int).SetBytes(s).Cmp(tlockStepOrder) < 0
tries = append(tries, H3Try{I: i, Digest: hex.EncodeToString(d), Shifted: hex.EncodeToString(s), Accepted: ok})
if ok {
return base, tries, s, nil
}
}
return nil, nil, nil, errors.New("H3: no try accepted")
}
func tlockStepXOR(a, b []byte) []byte {
out := make([]byte, len(a))
for i := range a {
out[i] = a[i] ^ b[i]
}
return out
}
func tlockStepBytes(p interface{ MarshalBinary() ([]byte, error) }) []byte {
b, err := p.MarshalBinary()
if err != nil {
panic(err)
}
return b
}
// tlockStepInput derives the sigma and the file key of stanza n of a round,
// deterministically.
func tlockStepInput(round uint64, n int) (sigma, fileKey []byte) {
var b [9]byte
binary.BigEndian.PutUint64(b[:8], round)
b[8] = byte(n)
return tlockStepHash(16, []byte("datekeys tlock_steps sigma"), b[:]),
tlockStepHash(16, []byte("datekeys tlock_steps file key"), b[:])
}
// TlockStepVectors computes testdata/vectors/tlock_steps.json. It builds
// each stanza with its own H2, H3 and H4 and checks every value against
// drand, kyber, tlock and agewrap: the message against DigestBeacon of the
// scheme, the hash to G1 against the pairing equation with the published
// signature, the body against tlock.TimeUnlock, kyber's DecryptCCAonG2 and
// the TimeIdentity of the reference, which recover the file key only if
// their H2, H3 and H4 are the ones written here. It also checks that the
// vectors tell the rules from their usual misreadings: the signature does
// not verify with the DST of G2 or with the round itself as the message, and
// clearing the top bit of a digest of H3 instead of shifting its first byte
// gives another r.
func TlockStepVectors() (TlockStepsFile, error) {
p := profile.Quicknet()
scheme, err := p.DrandScheme()
if err != nil {
return TlockStepsFile{}, err
}
if !bytes.Equal(ibe.H2Tag(), []byte(tlockStepH2Tag)) || !bytes.Equal(ibe.H3Tag(), []byte(tlockStepH3Tag)) || !bytes.Equal(ibe.H4Tag(), []byte(tlockStepH4Tag)) {
return TlockStepsFile{}, errors.New("the tags of kyber differ from the ones of spec §63")
}
if !bytes.Equal(bls.DefaultDomainG1(), []byte(tlockStepDST)) {
return TlockStepsFile{}, errors.New("the G1 DST of kyber-bls12381 differs from the one of spec §63")
}
suite := bls.NewBLS12381Suite()
key := scheme.KeyGroup.Point()
if err := key.UnmarshalBinary(p.PublicKey); err != nil {
return TlockStepsFile{}, err
}
g2 := suite.G2().Point().Base()
f := TlockStepsFile{
Spec: SpecVersion,
Description: "Steps 10 and 11 of spec §63 for Quicknet, value by value, over published releases. Step 10: M = SHA-256(uint64_be(round)), " +
"H(M) the hash to G1 of RFC 9380 with the suite BLS12381G1_XMD:SHA-256_SSWU_RO_ and the DST dst, and e(H(M), public_key) = e(signature, G2). " +
"Step 11: a stanza body U || V || W built with the sigma and the file key of the vector; H2 = SHA-256(\"IBE-H2\" || e(signature, U))[:16], " +
"sigma = V XOR H2, H4 = SHA-256(\"IBE-H4\" || sigma)[:16], file_key = W XOR H4, and r = H3(sigma, file_key): h3_base = SHA-256(\"IBE-H3\" || sigma || file_key), " +
"then for i = 1, 2, ... d = SHA-256(uint16_le(i) || h3_base), its first byte shifted one bit to the right, until it is below the order of the group; " +
"r·G2 = U. Generated by the reference implementation and checked against drand, kyber, tlock and agewrap. See testdata/README.md.",
Profile: p.ID,
Scheme: p.Scheme,
ChainHash: p.ChainHashHex(),
PublicKey: hex.EncodeToString(p.PublicKey),
DST: tlockStepDST,
Tags: TlockStepTags{
H2: hex.EncodeToString([]byte(tlockStepH2Tag)),
H3: hex.EncodeToString([]byte(tlockStepH3Tag)),
H4: hex.EncodeToString([]byte(tlockStepH4Tag)),
},
}
type input struct {
name string
round uint64
n int
}
inputs := []input{}
for _, round := range Rounds {
inputs = append(inputs, input{fmt.Sprintf("round %d, stanza 0", round), round, 0})
}
// The first stanza of round 1000 whose H3 needs at least three tries.
for n := 1; n < 256; n++ {
sigma, fk := tlockStepInput(1000, n)
if _, tries, _, err := tlockStepH3(sigma, fk); err == nil && len(tries) >= 3 {
inputs = append(inputs, input{fmt.Sprintf("round 1000, stanza %d: H3 accepts its try %d", n, len(tries)), 1000, n})
break
}
}
for _, in := range inputs {
v, err := tlockStepVector(scheme, suite, key, g2, p, in.round, in.n)
if err != nil {
return TlockStepsFile{}, fmt.Errorf("%s: %w", in.name, err)
}
v.Name = in.name
f.Vectors = append(f.Vectors, v)
}
return f, nil
}
func tlockStepVector(scheme *crypto.Scheme, suite pairing.Suite, key, g2 kyber.Point, p *profile.Profile, round uint64, n int) (TlockStepVector, error) {
release := Release(round)
m := tlockStepMessage(round)
if !bytes.Equal(m, scheme.DigestBeacon(&common.Beacon{Round: round})) {
return TlockStepVector{}, errors.New("M differs from DigestBeacon of the scheme")
}
// Step 10.
if err := provider.Verify(p, provider.Condition{Round: round}, release); err != nil {
return TlockStepVector{}, err
}
hm := suite.G1().Point().(kyber.HashablePoint).Hash(m)
sig := suite.G1().Point()
if err := sig.UnmarshalBinary(release.Signature); err != nil {
return TlockStepVector{}, err
}
if !suite.ValidatePairing(hm, key, sig, g2) {
return TlockStepVector{}, errors.New("e(H(M), public key) differs from e(signature, G2)")
}
// Another DST, the one of G2 that bls-unchained-on-g1 uses on G1, or the
// round without SHA-256, does not verify.
other := bls.NewBLS12381SuiteWithDST(bls.DefaultDomainG2(), nil).G1().Point().(kyber.HashablePoint).Hash(m)
raw := suite.G1().Point().(kyber.HashablePoint).Hash(binary.BigEndian.AppendUint64(nil, round))
if suite.ValidatePairing(other, key, sig, g2) || suite.ValidatePairing(raw, key, sig, g2) {
return TlockStepVector{}, errors.New("the signature verifies with another DST or another message")
}
// Step 11: the writer's side, with the H2, H3 and H4 of this file.
sigma, fk := tlockStepInput(round, n)
base, tries, rb, err := tlockStepH3(sigma, fk)
if err != nil {
return TlockStepVector{}, err
}
// The vector tells the shift of the first byte from clearing its top
// bit: that rule gives another r.
for _, t := range tries {
d, _ := hex.DecodeString(t.Digest)
d[0] &= 0x7f
if new(big.Int).SetBytes(d).Cmp(tlockStepOrder) < 0 {
if bytes.Equal(d, rb) {
return TlockStepVector{}, errors.New("clearing the top bit of H3 gives the same r")
}
break
}
}
r := suite.G1().Scalar()
if err := r.UnmarshalBinary(rb); err != nil {
return TlockStepVector{}, err
}
u := suite.G2().Point().Mul(r, nil)
gid := suite.Pair(hm, key)
gidr := tlockStepBytes(gid.Mul(r, gid))
h4 := tlockStepHash(16, []byte(tlockStepH4Tag), sigma)
ub := tlockStepBytes(u)
vb := tlockStepXOR(sigma, tlockStepHash(16, []byte(tlockStepH2Tag), gidr))
wb := tlockStepXOR(fk, h4)
body := slices.Concat(ub, vb, wb)
// The reader's side, recomputed.
gt := tlockStepBytes(suite.Pair(sig, u))
if !bytes.Equal(gt, gidr) {
return TlockStepVector{}, errors.New("e(signature, U) differs from e(H(M), public key)^r")
}
h2 := tlockStepHash(16, []byte(tlockStepH2Tag), gt)
if !bytes.Equal(tlockStepXOR(vb, h2), sigma) || !bytes.Equal(tlockStepXOR(wb, h4), fk) {
return TlockStepVector{}, errors.New("the decryption does not give back sigma and the file key")
}
// drand, kyber, tlock and agewrap decrypt it.
ct, err := tlock.BytesToCiphertext(*scheme, body)
if err != nil {
return TlockStepVector{}, err
}
got, err := tlock.TimeUnlock(*scheme, key, common.Beacon{Round: round, Signature: release.Signature}, ct)
if err != nil || !bytes.Equal(got, fk) {
return TlockStepVector{}, fmt.Errorf("tlock.TimeUnlock does not give back the file key: %v", err)
}
got, err = ibe.DecryptCCAonG2(bls.NewBLS12381Suite(), sig, ct)
if err != nil || !bytes.Equal(got, fk) {
return TlockStepVector{}, errors.New("kyber's DecryptCCAonG2 does not give back the file key")
}
id, err := agewrap.NewTimeIdentity(p, round, release)
if err != nil {
return TlockStepVector{}, err
}
got, err = id.Unwrap([]*age.Stanza{{Type: agewrap.StanzaTLock, Args: []string{strconv.FormatUint(round, 10), p.ChainHashHex()}, Body: body}})
if err != nil || !bytes.Equal(got, fk) {
return TlockStepVector{}, fmt.Errorf("agewrap.TimeIdentity does not give back the file key: %v", err)
}
return TlockStepVector{
Round: round,
Signature: hex.EncodeToString(release.Signature),
Message: hex.EncodeToString(m),
HashToG1: hex.EncodeToString(tlockStepBytes(hm)),
Body: hex.EncodeToString(body),
U: hex.EncodeToString(ub),
V: hex.EncodeToString(vb),
W: hex.EncodeToString(wb),
Pairing: hex.EncodeToString(gt),
H2: hex.EncodeToString(h2),
Sigma: hex.EncodeToString(sigma),
H4: hex.EncodeToString(h4),
FileKey: hex.EncodeToString(fk),
H3Base: hex.EncodeToString(base),
H3Tries: tries,
R: hex.EncodeToString(rb),
}, nil
}

File diff suppressed because it is too large Load Diff

@ -54,7 +54,15 @@
to may be an address of NAT64 whose IPv4 address inside is public, so that
a reader on an IPv6-only network downloads the rest of an envelope. Its §76
records the change with its case.
- `datekeys.cddl`: the CBOR schemas of v0.13, the same as those of v0.12, the three control
- `DateKeys_Protocol_Specification_v0.14.md`: the draft v0.14, work in
progress and not approved; the branch `v0.14` implements it. It changes no
format and no verdict: it writes down what the completeness review of
6 October 2026 found missing (what the protocol does not guarantee, the
provider, quantum risk to signatures, the web client, the entropy of a key
of words, the states of a profile) and the root of trust byte for byte:
the message a Quicknet round signs, its hash to G1, and H2, H3 and H4 of
the tlock IBE. Its §76 records each change with its case.
- `datekeys.cddl`: the CBOR schemas of v0.13, the same as those of v0.12 and unchanged in the draft v0.14, the three control
versions and the security and head objects of format 3 included, with the
encoding rules CDDL cannot express. Those of v0.9 and v0.8.2 are at the tags
`spec-v0.9` and `spec-v0.8.2`.

82
testdata/README.md vendored

@ -48,6 +48,7 @@ Conventions for every file:
| `vectors/dk1.json` | canonical `dk1_` strings, and rejected encodings with their code | §18, §19, §66 |
| `vectors/cbor.json` | the CBOR profile, and one block of vectors per schema, CONTROL_CBOR in the three formats | §58, CDDL |
| `vectors/tlock_ibe.json` | H2 of the tlock IBE: the serialization of an element of GT | §63 step 11 |
| `vectors/tlock_steps.json` | steps 10 and 11 for Quicknet value by value: the message of a round, its hash to G1, and the decryption of a tlock stanza with H2, H4, H3 and the file key | §63 steps 10 and 11 (v0.14) |
| `vectors/padding.json` | the padding of formats 2 and 3: P for each content length L, and the length of PAYLOAD_AGE | §29.1 |
| `vectors/paths.json` | the paths of a format 3 head: the rules of one entry, and those of the paths of a head | §29.5 |
| `vectors/path_fold.json` | the key of R7 of segments, and their NFD | §29.5, §29.5.1 |
@ -311,6 +312,87 @@ serialization at once. The same 576 bytes with the twelve coordinates of Fp in
reverse order, c0 first at every level as `Fp12.toBytes` of `@noble/curves`
writes them, give `0118eea9d5971745f71e3c94926f1717` and another FK_TIME.
## `vectors/tlock_steps.json`
Steps 10 and 11 of spec §63 for Quicknet, every intermediate value written
out, over the published releases of rounds 1000, 1001, 1004 and 2000 (spec
v0.14: the paragraphs "Mensaje de ronda y hash a G1" and "H3 y H4" after the
flow).
```json
{
"spec": "0.14",
"description": "…",
"profile": "datekeys:quicknet:v1",
"scheme": "bls-unchained-g1-rfc9380",
"chain_hash": "52db…",
"public_key": "83cf…",
"dst": "BLS_SIG_BLS12381G1_XMD:SHA-256_SSWU_RO_NUL_",
"tags": { "h2": "4942452d4832", "h3": "4942452d4833", "h4": "4942452d4834" },
"vectors": [
{
"name": "round 1000, stanza 0",
"round": 1000,
"signature": "b446…",
"message": "f652…",
"hash_to_g1": "8f5a…",
"body": "a73e…", "u": "a73e…", "v": "f628…", "w": "b799…",
"pairing": "13dc…",
"h2": "…", "sigma": "…", "h4": "…", "file_key": "…",
"h3_base": "…",
"h3_tries": [ { "i": 1, "digest": "…", "shifted": "…", "accepted": true } ],
"r": "20fd…"
}
]
}
```
Every byte string is hex. The top-level fields are those of the pinned
profile (spec §12), the DST of the hash to G1 as text and the tags of H2, H3
and H4 as bytes: the ASCII of `IBE-H2`, `IBE-H3` and `IBE-H4`.
Step 10, the release:
- `signature`: the published signature of `round`, the release, compressed in
G1 (spec §12.2).
- `message`: M = SHA-256 of the round as 8 bytes big-endian, the message an
unchained drand scheme signs.
- `hash_to_g1`: H(M), hash_to_curve of RFC 9380 with the suite
`BLS12381G1_XMD:SHA-256_SSWU_RO_` and the DST `dst`, compressed. The
signature verifies: e(H(M), `public_key`) = e(`signature`, G2), with G2 the
generator of G2.
Step 11, one tlock stanza of the round:
- `body`: the stanza body U || V || W, 128 bytes, and `u`, `v` and `w` its
three parts: U compressed in G2, V and W of 16 bytes.
- `pairing`: e(`signature`, U), 576 bytes in the order of `tlock_ibe.json`.
- `h2`: SHA-256 of `IBE-H2` and `pairing`, truncated to 16 bytes.
- `sigma`: V XOR `h2`.
- `h4`: SHA-256 of `IBE-H4` and `sigma`, truncated to 16 bytes.
- `file_key`: W XOR `h4`, FK_TIME, the file key of OUTER_TIME_AGE.
- `h3_base`: SHA-256 of `IBE-H3`, `sigma` and `file_key`.
- `h3_tries`: the tries of H3, in order. Try `i` hashes the counter `i` as 2
bytes little-endian followed by `h3_base` (`digest`), then shifts the first
byte of the digest one bit to the right (`shifted`); the try is accepted
when `shifted`, read as a big-endian integer, is below the order r of the
groups (spec §12.2). Only the last try is accepted. The shift moves every
bit of the first byte; clearing only its top bit gives another r.
- `r`: the accepted `shifted`, the scalar of the check r·G2 = U.
The last vector is the first stanza of round 1000, in the order of the
generator, whose H3 needs at least three tries: it accepts its fourth, where
clearing the top bit would accept the second. A reader checks every value
in this order and the check r·G2 = U.
The generator chooses `sigma` and `file_key` per stanza, derives r, U, V and W
with its own H2, H3 and H4, and checks the result against the libraries the
reference uses: `message` against `DigestBeacon` of the drand scheme,
`hash_to_g1` against the pairing equation with the published signature, and
the body against `tlock.TimeUnlock`, `DecryptCCAonG2` of drand/kyber and the
tlock identity of `agewrap`, which give back `file_key` only if their H2, H3
and H4 are the ones written here.
## `vectors/padding.json`
The padding of the payload of a capsule of format 2 or 3, spec §29.1, where L

@ -0,0 +1,164 @@
{
"spec": "0.13",
"description": "Steps 10 and 11 of spec §63 for Quicknet, value by value, over published releases. Step 10: M = SHA-256(uint64_be(round)), H(M) the hash to G1 of RFC 9380 with the suite BLS12381G1_XMD:SHA-256_SSWU_RO_ and the DST dst, and e(H(M), public_key) = e(signature, G2). Step 11: a stanza body U || V || W built with the sigma and the file key of the vector; H2 = SHA-256(\"IBE-H2\" || e(signature, U))[:16], sigma = V XOR H2, H4 = SHA-256(\"IBE-H4\" || sigma)[:16], file_key = W XOR H4, and r = H3(sigma, file_key): h3_base = SHA-256(\"IBE-H3\" || sigma || file_key), then for i = 1, 2, ... d = SHA-256(uint16_le(i) || h3_base), its first byte shifted one bit to the right, until it is below the order of the group; r·G2 = U. Generated by the reference implementation and checked against drand, kyber, tlock and agewrap. See testdata/README.md.",
"profile": "datekeys:quicknet:v1",
"scheme": "bls-unchained-g1-rfc9380",
"chain_hash": "52db9ba70e0cc0f6eaf7803dd07447a1f5477735fd3f661792ba94600c84e971",
"public_key": "83cf0f2896adee7eb8b5f01fcad3912212c437e0073e911fb90022d3e760183c8c4b450b6a0a6c3ac6a5776a2d1064510d1fec758c921cc22b0e17e63aaf4bcb5ed66304de9cf809bd274ca73bab4af5a6e9c76a4bc09e76eae8991ef5ece45a",
"dst": "BLS_SIG_BLS12381G1_XMD:SHA-256_SSWU_RO_NUL_",
"tags": {
"h2": "4942452d4832",
"h3": "4942452d4833",
"h4": "4942452d4834"
},
"vectors": [
{
"name": "round 1000, stanza 0",
"round": 1000,
"signature": "b44679b9a59af2ec876b1a6b1ad52ea9b1615fc3982b19576350f93447cb1125e342b73a8dd2bacbe47e4b6b63ed5e39",
"message": "f652498d092acd949bad74e40683bf3824fb817980504a0c7e6722cfc5a9c0a3",
"hash_to_g1": "8f5a32d53837b00fbc0ee31ce9966435a41c5188a80ce9934d3c80588b6ad6f643ebda1b83ef89e44da9ced6205cdecf",
"body": "a73eb63b9a766ebbd23e06daa313760b001502ab48de4976c98c1697ebd51907c2ab92306e4d04ee9f42bff92775ba6606f08479fbd58a3fb786c94a27bf924c67975f419d5b67b96080b4a3da776eddc762ce07af0a5b5a0965f64a9902f4d3f62867846361583f06a8978ae6876e0eb799ebe3cf0b0bf967921fc5e6eb85d9",
"u": "a73eb63b9a766ebbd23e06daa313760b001502ab48de4976c98c1697ebd51907c2ab92306e4d04ee9f42bff92775ba6606f08479fbd58a3fb786c94a27bf924c67975f419d5b67b96080b4a3da776eddc762ce07af0a5b5a0965f64a9902f4d3",
"v": "f62867846361583f06a8978ae6876e0e",
"w": "b799ebe3cf0b0bf967921fc5e6eb85d9",
"pairing": "13dc0e183d402040f68cb518c39c5fcfc61852058d0d58f962ec5649d3da484f62f8562cb4fa6b576d2882bac78ce474100a3086d82617f2b9ba844f6e2569e5b0c3c81ca94aa9ecda8909baabf16bfd4d95602b0ad3263aaaeb14748d41e9e30c811671230b41b54e5cce08f3d3ef671a411850c165dad83824fb91380554f5dd9ea3005738c83e264d58b3b28c275a0409076922ff12b9b1421d70c958c22a29da81a7df5f93a7d5f32d187e82a1f34ed60c01e9bb0685c0f773cb324b0e8118c5a8cee62b795b8fa7d5e820aa08003462a5521d70beabebb7f74022163286256eaeab18148d7caf9a0057fe37e6de0f10c412dd62f013e62a21971bae6d3957fd326aaa809348da278e812637343a20c942263da247497748aa5c39b945bd112fe3afbf5508117b48b1017931e9dfa97e3a9eaffef3add91ed62ec2814eb9063ffb64943e0b302efb12e3ff680d99199e068714b0c0d6d295a6019a6e325def3cd58c7c20c2196ba7fe28d67b9bf385764d81c63c02f6333d4fc5dbf5e1171913e06b904367571b8d2811f7288c18be3831d907ebc7f03ab6014282bcc362f1a3b0d12bbfc9cd9ba1d255254d64a216151c040975fd726c51fe191b3c675fc6ebc79b9a1f123e15059955761732f66cbb13c45868881fbbe08b21cf677551120e80ef555a5db93283f5b99714e997028eb1380e1a3db0bdc55d269f736e2b9f584c2661e460d3a6ce2db9a1aa902a02b16d5b9f634e96c5d615d3e1be0c232e13723d6f9b93686b1b9bee950ed45e729b3bd6d448badc0816fb8b9360bf28",
"h2": "c3d489f4c7c6a6962801cad91047eb95",
"sigma": "35fcee70a4a7fea92ea95d53f6c0859b",
"h4": "bd093650d9bd27e682b48bc3ba52a0aa",
"file_key": "0a90ddb316b62c1fe52694065cb92573",
"h3_base": "c8b1566b6f0ed7b6cfea5eebaa1a7291f77f50c80dfd8269e9b4f253fff23fe0",
"h3_tries": [
{
"i": 1,
"digest": "41fd905b124c321e66a781f9eec59842d08689c872f4eaada61c921f8b6e6a8e",
"shifted": "20fd905b124c321e66a781f9eec59842d08689c872f4eaada61c921f8b6e6a8e",
"accepted": true
}
],
"r": "20fd905b124c321e66a781f9eec59842d08689c872f4eaada61c921f8b6e6a8e"
},
{
"name": "round 1001, stanza 0",
"round": 1001,
"signature": "b33bf3667cbd5a82de3a24b4e0e9fe5513cc1a0e840368c6e31f5fcfa79bea03f73896b25883abf2853d10337fb8fa41",
"message": "ce43c3353a7ad7aac3408cad0bf921b6a7dda89be75d9cb2b3b5a152cefc8afd",
"hash_to_g1": "8dafa08d032514b04972cd9bca0c40226294bc9dc8b02d10ed4b3913554571e04f20d7eb05b74cddf72a9992995ac5bb",
"body": "ad4937a39b57f8c494817575bf3cac373ed629b3580d374953f08df5c59e00f76abbe58ec09704b544464975a843255307d45413ad277661ac6d361afa687bd40f2745fb9c4498882fbb91269350ab975fc1a1a83d2c5f7d127786779c01e55ee512d80ed32c46da0c915a5459244507444e2b3f156d72748fa2c3ee40120dee",
"u": "ad4937a39b57f8c494817575bf3cac373ed629b3580d374953f08df5c59e00f76abbe58ec09704b544464975a843255307d45413ad277661ac6d361afa687bd40f2745fb9c4498882fbb91269350ab975fc1a1a83d2c5f7d127786779c01e55e",
"v": "e512d80ed32c46da0c915a5459244507",
"w": "444e2b3f156d72748fa2c3ee40120dee",
"pairing": "06bf5fa844026aff0c454df2da4f46f769b6db78c68bdfdafacc1aee0d9d57b40603c0a043478a4785c635587896068701fcbc9ef9f489e53c2f30709136404cbb04c9b0ba0b74e26708f53735209f6f5cfa76fefff64a2db62726745db1693711a09a514fc2925ac383494d6882edb9d2c5143f9f2e8b2b25dfcaf1ac03ca6e9e0bfa989f3e1ebbe0a63345bfe1b9e40657b0fdb63c0646e2fef7f48e73861a364fbc944380af8e989e897a0037e54a1766086a1ea7c9457f47ff7521ac175d0e80ac41a06b949e12ac4c131354371f34318d9559bbdbdb8a9b7bd415b4b64542f240d4d3b69f350614fce76cbeb83b09457cc90c73da60247b929ca72602ba0e3c47653f6e798ffdac42f85039f2d43b817647536f369cea55812d08aa1ca80b9854d9b951ded8c1fa0053377711320de0ca459a84983ce49d68446a5d1c757afeffc896b146c2198b3a171854910d04fa8559d6018affc7c4e35760dc1ac4d90c83821e383ecdaa7ee3eda64e3ac4fa43648e7e821caddcbcabf3e34f5ea30e962c6aa7e6de1e72b3362311c5506607b180a79920c14961b9f8c850227bca1c0b59acffc7a79bf48bfde53fde6031185598646a15c7eb55df63e7fe8f930c6be0e8d6ee695608114f511c83a3c98b2e376cedc16b41c6c94acfb7180287d4007e4eeaf3bb6cd8bf67014302f47626346526358b3acec4cd9f7b083cdeed60c632c8007d0e4d88e252e6a3b8a955d216d6991a2893a56117cdebee0c78d7364f54f45313d472de5dd1e426b3483100107614137b08c38b7f139ab8adb05e33",
"h2": "d1c48e9d72ef4e29581947627078779e",
"sigma": "34d65693a1c308f354881d36295c3299",
"h4": "b05c539a1ce0d4b2f881e2a899bd648b",
"file_key": "f41278a5098da6c677232146d9af6965",
"h3_base": "f89b77b992969b10442252a826f0380716867ee3f2270cd6705b4ffbe474c727",
"h3_tries": [
{
"i": 1,
"digest": "85e7c45f27c75fa2571403fc7cd8222e0dfbdddd7842f85e814854c507abdfc6",
"shifted": "42e7c45f27c75fa2571403fc7cd8222e0dfbdddd7842f85e814854c507abdfc6",
"accepted": true
}
],
"r": "42e7c45f27c75fa2571403fc7cd8222e0dfbdddd7842f85e814854c507abdfc6"
},
{
"name": "round 1004, stanza 0",
"round": 1004,
"signature": "a40658b820c0f8c10207524179a2031ba9537688a0d04e4851b58026be9a341fee3b96fb48ffad28483d84b40a5864aa",
"message": "dfb0ecda8fd28db758bd0c580c0bb9397b56225bd50f076bac68460e68d0ea00",
"hash_to_g1": "895a4b04764f8964e42a056c23d7b34808895603f605ee0f749f8be419420b53a0ba5e01caab02e8afd7ff28c6cd771f",
"body": "97b8304c3e87868e549a6293d19d65481bdbcf7cf67b9d5e3d798ade332deb499648fe2f23931ab55b0911ccdc8839560f5a72325eedc7302420bd87bcafd7f27f2eadbc90523a295e5ab476b357ca91b9a8b5e45a4dac972f20b37e97e8945d96ce47d18a7e845031e28207606a7ea78a4f271ed5ed8d3ed9420fe99200396a",
"u": "97b8304c3e87868e549a6293d19d65481bdbcf7cf67b9d5e3d798ade332deb499648fe2f23931ab55b0911ccdc8839560f5a72325eedc7302420bd87bcafd7f27f2eadbc90523a295e5ab476b357ca91b9a8b5e45a4dac972f20b37e97e8945d",
"v": "96ce47d18a7e845031e28207606a7ea7",
"w": "8a4f271ed5ed8d3ed9420fe99200396a",
"pairing": "0b57e9394946ebc2e4ec7478308fe77ab5b509f00727d46dec4d8635bb7934b4c485f3408c974d45468c2363a768ee18172c3f56f94c6bea5f8658cfc79bc3cafdf3dc418134f4cea86e14b1c73ca85456cb56ac4438862d5093447e97afd795169452925b396bb07823cd1d4a5b9a7b58355170a713a0a14a3ff568a27f57743890c26387ef0f15c49057d8cc74857e0874d72f661e9cecd3b97443aaf64e0703ed453ff9ffb659070d81a40fd0c92ed1221d5d0767e0bb6e6d72c3979fe57619cc78dbd491b3629b21668beab4bdcf787ab581c62211f17db4a61d2ff5946178d1d29448c7bce8a664220bb2fd928d1926ddc1fa2d65f47a60bee3f1375a49cad2a5d0c5406f51ccf6d18e537b820da2112350f6a97b2fc76111b7ec8c0ae11484bd6d622de8b58cbb79ad193d285a49333040cdcf4aabd532cf5465248d4234b41a72614aabfe23479926e6b6635d003901ecd863d063befa706baba0b7aba385e7396b78a20f8e7738c7ec14e340b80e8cfeb5509e8bb47807a82fea6b6215a3f4ce9786623a283a4b07d5aa07fcf9636122a6dee64db8b4280c24e2e909bc791cc9d11adf6cacd82823fdf43873171d52f3d9bc035d3f9bb63eaaaa27e3109b7324f2828e6dc2ce78324bff9a92b9c569ab51ed714e70afd1687d5188f60e1ab87bd7db3ffedec49b52dd0a09909be3cc96156b82d0ab49adfd64c24faf9cd574d9c585829f3fd608c7df754a58045f1545128a0030459cc766fbaf636ce19be4d4537ac181cd9bd2da65cb93257b72984bcf0c74b19247d15c680fd278",
"h2": "ed9e2e9ca7679f40d9d5461808d3902d",
"sigma": "7b50694d2d191b10e837c41f68b9ee8a",
"h4": "8aa64ea323262cff566c987b5467ae3a",
"file_key": "00e969bdf6cba1c18f2e9792c6679750",
"h3_base": "cbf54def509294ab547c383ea065b02d2bec599d6a41f41b3083dad3ff7b2459",
"h3_tries": [
{
"i": 1,
"digest": "060304f06ac573eee1c4ed5b125d6f8ae7c9f154c60156c4e37de84ebc9846cb",
"shifted": "030304f06ac573eee1c4ed5b125d6f8ae7c9f154c60156c4e37de84ebc9846cb",
"accepted": true
}
],
"r": "030304f06ac573eee1c4ed5b125d6f8ae7c9f154c60156c4e37de84ebc9846cb"
},
{
"name": "round 2000, stanza 0",
"round": 2000,
"signature": "b6cb8f482a0b15d45936a4c4ea08e98a087e71787caee3f4d07a8a9843b1bc5423c6b3c22f446488b3137eaca799c77e",
"message": "597962656abdc948a536fcd5ba8405e6bd95b9763f4a4da0727e8c98689d52c2",
"hash_to_g1": "906dc77479bc9962a8ed67fd00ad6af2a6c8d109926fdd6b897fe77526b2531b544b5e8703de23748b6ae6172b9986f5",
"body": "ab73f3818b2170ec27e8c6ad89232453199c2ceb781e920fb8058947ade9a12daf99775f384f575daae76fb76c1bb40e00754fd1515534b2f1c315108a568bb7405a5829eba26e3a1ac08178e73ac13bca55a0ef7eeb8980d0a4424b84ac47ff04cbb545b21b4ebcc651055043dd6f7b216b730fe903e9c7824eadef6522c2d9",
"u": "ab73f3818b2170ec27e8c6ad89232453199c2ceb781e920fb8058947ade9a12daf99775f384f575daae76fb76c1bb40e00754fd1515534b2f1c315108a568bb7405a5829eba26e3a1ac08178e73ac13bca55a0ef7eeb8980d0a4424b84ac47ff",
"v": "04cbb545b21b4ebcc651055043dd6f7b",
"w": "216b730fe903e9c7824eadef6522c2d9",
"pairing": "07999e22e3e3e73a814ff2ff0329f87749396dc9b6a2e6f0520b01df4f73935cce76c3197164eb129f03b72675d05d8318f73d35d748b4fadc36cb7bff193e44bc30a795377a5faaae2649fc89df82539b177defcd3122e1ef461f869e22ab80165c6c07fbc3ed5752921287c8dc5177cbbf19c14b84fce0393d4cd2bd9dc8f569964e88d82cca5df637019bf6b3f9230ca4d83f519082c62919b1d5138326cd97af77bf54a8257c677f1162c603f181f0f74dbc5c4558ade7adf44d6689213804028a36cb0597d58a1a777bb187479ae7e69214f632a53fdb93c9580bf71d1cf91076830ca73bf548417e9729a53ad400a89f83721daa9e2a1b963b9cd2b9a6c68bd17b61039d08f4ff9962deef188b597cbf5855dcefc6e4192d4ad4984a2a05929fc3c0043f53f63bca31ae676883ca550ac47c06dad52a95366ccec9f03a2eb6c4fdb15df0238a991f4245a740b00b1762bb3c76709333e758be369616ea68929eadc0eee12b1f074707db5153d2b07fa99db5bff8f6ba04f318c9f4abf6175c1d5471c150ffd8e1cd83ed6e26c3eaa821aa4c4724dbfd644b0df28a80134c0fc2334e34c2b591a79b531b116abf1363314b98b21a669ca179bb7065336df05315a8885f32db74d56884c01ab37ecd0dfcde9b4d23a3481bd487d6e5f523089f89ed52d7e50a48a591306eea76b353ea2c63f14826b8a785ce9a7cafddd5b5d6d6a89773c2b24a178b6e6d3f1f2002d7c409b2c7312df81c21af3ba95ec8646e64ac240a43e6e8245f3ec2532a10ea917c0dac568cb468bad84562acf72c",
"h2": "0b214ea01f127a78f8af587331314ce0",
"sigma": "0feafbe5ad0934c43efe5d2372ec239b",
"h4": "5097513c5c6ad5a8e614205284b46f9a",
"file_key": "71fc2233b5693c6f645a8dbde196ad43",
"h3_base": "2a1ca2b9377eae364c9874c19450c74919f88bd0e4d05153fcadc373db2d3989",
"h3_tries": [
{
"i": 1,
"digest": "59d0a91dbc2ea95a7ded3610fd282f2c0286459e49fe275bce5185501df3a106",
"shifted": "2cd0a91dbc2ea95a7ded3610fd282f2c0286459e49fe275bce5185501df3a106",
"accepted": true
}
],
"r": "2cd0a91dbc2ea95a7ded3610fd282f2c0286459e49fe275bce5185501df3a106"
},
{
"name": "round 1000, stanza 111: H3 accepts its try 4",
"round": 1000,
"signature": "b44679b9a59af2ec876b1a6b1ad52ea9b1615fc3982b19576350f93447cb1125e342b73a8dd2bacbe47e4b6b63ed5e39",
"message": "f652498d092acd949bad74e40683bf3824fb817980504a0c7e6722cfc5a9c0a3",
"hash_to_g1": "8f5a32d53837b00fbc0ee31ce9966435a41c5188a80ce9934d3c80588b6ad6f643ebda1b83ef89e44da9ced6205cdecf",
"body": "b326f73120b5a037953e1b58da50d242e8766a4ade2ac5113685210dfe09d63a2ae1e02e8f1dab5214c68d9fd739e6450ccf379e9e47323e993ac94d91af16d4b38157af7bd098ece86f9d2ceb06b93da6d295e1b18a6eba255a95ed50c869d5f6c14db7259bc069fe1b69cb2d562349e6407fe52ab31aa27b7cc4c859564e33",
"u": "b326f73120b5a037953e1b58da50d242e8766a4ade2ac5113685210dfe09d63a2ae1e02e8f1dab5214c68d9fd739e6450ccf379e9e47323e993ac94d91af16d4b38157af7bd098ece86f9d2ceb06b93da6d295e1b18a6eba255a95ed50c869d5",
"v": "f6c14db7259bc069fe1b69cb2d562349",
"w": "e6407fe52ab31aa27b7cc4c859564e33",
"pairing": "00585d6ec0a2617f28a00b0455e9ea364ec343489aa7f67f046ba13fc40a800d032c89a0ca5cc33761a02c2de95383650ecf9bbbc77ce2322cd225e6775e7a8e39ad0ed6e3bca1213ff44e52bce0a629e5c69cdd380e0448969b253d12e2baa8131b9e81906e44795535bbf276371d6db833ff9e0c96b76ed960e18c9c8a2b9032880bfebc681f0802d0f00b4768317c0246c202f18c369b5fe659353ee0dd803aed4fd66c98b6402ed811ca348741efff0f88ed32fdd65070bda0a63b30dfcd0c24962dad0b5587f8fc39630d37aea45f50ef458c000884b9b51ee2599496aa61b7b916ed873c6c7f11ef1db2a41cb003df3d757e4f61e5c13beb19d0fd9ebbcb15559e6252bbc5d0faae267dc7f5b25f5f2b4e3295bc4d17b308553e28599911d75b66f3f1d5d6a2795cf9bf3f154654d8bd8e64bea438cecaddee75093cf5efc7579ac55e0b5a76ae767264df544a0fdd0e95b9310d24d7bbb3a4df3bc3ae3d251d3970e483c5d4b10870409c7620531cb9d41670835f2306ac0acdd7524312eeb7b9d83de7c623724eba86ea0a7b10bbc6efecf440681271c5c3d980a975637dd26c99f632e003a9f54045bcb1df0abca2ce0afe6bb1cd383fc34efb72ae0afa3db33ac715a371e3fdfe1e28385e775b5e19e1a49ff265ce2238483c342803dd1ae3f72ecd82f17aa1207fa1f32f2c9f89c38488a381d987e90810753462d7003210c6f66b8ff590055b143b553c0825f4bac496509f88698485173da385b2230f44275eb55a3da686e12680fcb175062007100161ed9bf6de51976739c3",
"h2": "2271ed3feb6223f3f21e7fcecb89f30b",
"sigma": "d4b0a088cef9e39a0c051605e6dfd042",
"h4": "085c839d518ebc5636d8642df86b6f2b",
"file_key": "ee1cfc787b3da6f44da4a0e5a13d2118",
"h3_base": "a5dd9d066f9fdd547d25616b65c9ea76e5da38392ca02853a20ebb2c7d01fc11",
"h3_tries": [
{
"i": 1,
"digest": "f647f4537bc552e6d82a22abbef3397f1adfbe51933df3fda8b60e9d927fd9a1",
"shifted": "7b47f4537bc552e6d82a22abbef3397f1adfbe51933df3fda8b60e9d927fd9a1",
"accepted": false
},
{
"i": 2,
"digest": "f20b12601c3bae738eea421aba70ccfb7df494791c004bf5f028972258c1d15a",
"shifted": "790b12601c3bae738eea421aba70ccfb7df494791c004bf5f028972258c1d15a",
"accepted": false
},
{
"i": 3,
"digest": "f45606605279cfaffabaadda379d52a5ae0aa5453447244b702b1588e7be4200",
"shifted": "7a5606605279cfaffabaadda379d52a5ae0aa5453447244b702b1588e7be4200",
"accepted": false
},
{
"i": 4,
"digest": "a495752b48f0bcd717b4e3846ed0501b4085621321ca846b2710d805d0790699",
"shifted": "5295752b48f0bcd717b4e3846ed0501b4085621321ca846b2710d805d0790699",
"accepted": true
}
],
"r": "5295752b48f0bcd717b4e3846ed0501b4085621321ca846b2710d805d0790699"
}
]
}
Loading…
Cancel
Save

Powered by TurnKey Linux.