git://y.git.stargrave.org/keks.git
git://y.git.cypherpunks.su/keks.git
-Also there is Yggdrasil accessible address: http://y.www.keks.cypherpunks.su/
+Also there is Yggdrasil accessible address:
+=> http://y.www.keks.cypherpunks.su/\r
=> https://yggdrasil-network.github.io/ Yggdrasil\r
IV = HKDF-Expand(H, prk=CKi, len=8, info="cm/encrypted/kuznechik-ctr-hmac-kr/iv")
Kauth || KauthTail = HKDF-Expand(H, prk=CKi,
info="cm/encrypted/kuznechik-ctr-hmac-kr/auth")
- KauthTail = HKDF-Expand(H, prk=CKi,
- info="cm/encrypted/kuznechik-ctr-hmac-kr/authTail")
- CT = Kuznechik-CTR(key=Kenc, ctr=IV, data=chunk)
- CT || HMAC(Streebog-256, key={Kauth|KauthTail}, data=CT)
+ CIPHERTEXT = Kuznechik-CTR(key=Kenc, ctr=IV, data=chunk)
+ CIPHERTEXT || HMAC(Streebog-256, key={Kauth|KauthTail}, data=CIPHERTEXT)
+
+Chaining key (CK) advances with every chunk. 256-bit encryption key and
+randomised 64-bit nonce (initialisation vector) are derived from it.
KauthTail is used only in the last chunk to explicitly signal
that it is the last one.
CKi = HKDF-Extract(H, salt="", ikm=CK{i-1})
KEY = HKDF-Expand(H, prk=CKi, info="cm/encrypted/xchapoly-krkc/key")
IV = HKDF-Expand(H, prk=CKi, info="cm/encrypted/xchapoly-krkc/iv", len=24)
- if last chunk { IV[23] |= 0x01 } else { IV[23] &= 0xFE }
+ if {last chunk} then { IV[23] |= 0x01 } else { IV[23] &= 0xFE }
CIPHERTEXT || TAG = XChaCha20-Poly1305(key=KEY, ad="", nonce=IV, data=chunk)
COMMITMENT = BLAKE2b-256(KEY || IV || TAG)
CIPHERTEXT || TAG || COMMITMENT
"/payload"'s chunk length equals to 128KiB+16+32 bytes.
=> https://datatracker.ietf.org/doc/html/rfc5869.html RFC 5869, HKDF\r
-=> https://www.blake2.net/ BLAKE2b is hashing algorithm\r
-=> https://datatracker.ietf.org/doc/html/rfc7693.html RFC 7693, same\r
+=> https://datatracker.ietf.org/doc/html/rfc7693.html RFC 7693, BLAKE2b\r
=> https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-xchacha XChaCha20-Poly1305 AEAD\r
=> https://datatracker.ietf.org/doc/html/rfc8439.html RFC 8439\r
XChaCha20-Poly1305 with key ratcheting and multi-recipient DEM.
[cm/encrypted/]'s "/dem/a" equals to "xchapoly-krmr".
-CEK consists of common 64 bytes long part equal in all KEMs (@code{CEK} itself),
-and 64 bytes long per-KEM/per-recipient random MAC key (@code{prMAC}).
+CEK consists of common 64-bytes part equal in all KEMs (CEK itself),
+and 64 bytes long per-KEM/per-recipient random MAC key (prMACx).
Data is split on 128 KiB chunks, each of which is encrypted the following way:
H = BLAKE2b
CK0, prMACx0 = CEK || prMACx
CKi = HKDF-Extract(H, salt="", ikm=CK{i-1})
+ prMACxi = HKDF-Extract(H, salt="", ikm=prMACx{i-1})
KEY = HKDF-Expand(H, prk=CKi, info="cm/encrypted/xchapoly-krmr/key")
IV = HKDF-Expand(H, prk=CKi, info="cm/encrypted/xchapoly-krmr/iv", len=24)
- if last chunk { IV[23] |= 0x01 } else { IV[23] &= 0xFE }
+ if {last chunk} then { IV[23] |= 0x01 } else { IV[23] &= 0xFE }
CIPHERTEXT || TAG = XChaCha20-Poly1305(key=KEY, ad="", nonce=IV, data=chunk)
- prMACxi = HKDF-Extract(H, salt="", ikm=prMACx{i-1})
MACx = BLAKE2b-256-MAC(key=prMACxi, H(CIPHERTEXT || TAG))
CIPHERTEXT || TAG || MACx || MAC{x+1} [|| MAC{x+2} ...]
"/payload"'s chunk length equals to 128KiB+16+32*recipients bytes.
=> https://datatracker.ietf.org/doc/html/rfc5869.html RFC 5869, HKDF\r
-=> https://www.blake2.net/ BLAKE2b is hashing algorithm\r
-=> https://datatracker.ietf.org/doc/html/rfc7693.html RFC 7693, same\r
+=> https://datatracker.ietf.org/doc/html/rfc7693.html RFC 7693, BLAKE2b\r
=> https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-xchacha XChaCha20-Poly1305 AEAD\r
=> https://datatracker.ietf.org/doc/html/rfc8439.html RFC 8439\r
If absent, then null UUID is used in KDF.
[cm/encrypted/authcrypt] -- authenticated public-key encryption
-[cm/keywrap/] -- key wrapping mechanisms
-[cm/dem/] -- data encapsulation mechanisms
-[cm/kem/] -- key encapsulation mechanisms
+[cm/keywrap/] | key wrapping mechanisms
+[cm/dem/] | data encapsulation mechanisms
+[cm/kem/] | key encapsulation mechanisms
[cm/hashed/] with BLAKE2b.
+=> https://datatracker.ietf.org/doc/html/rfc7693.html RFC 7693, BLAKE2b\r
BLAKE2b with 512-bit output has "blake2b" algorithm identifier.
256-bit output has "blake2b256" algorithm identifier.
-=> https://www.blake2.net/ BLAKE2b\r
-=> https://datatracker.ietf.org/doc/html/rfc7693.html RFC 7693, same\r
[cm/hashed/] with BLAKE3.
-BLAKE3 with fixed 256-bit output has "blake3" algorithm identifier.
=> https://github.com/BLAKE3-team/BLAKE3/ BLAKE3\r
+BLAKE3 with fixed 256-bit output has "blake3" algorithm identifier.
[cm/hashed/] with SHAKE.
+=> https://keccak.team/ SHAKE\r
SHAKE XOF function with fixed 256 (SHAKE128) or 512 (SHAKE256) bit output.
"shake128", "shake256" algorithm identifiers are used.
-=> https://keccak.team/ SHAKE\r
[cm/hashed/] with Skein-512.
-"skein512" algorithm identifier is used.
=> https://www.schneier.com/academic/skein/ Skein-512\r
+"skein512" algorithm identifier is used.
[cm/hashed/] with GOST R 34.11-2012.
+=> https://datatracker.ietf.org/doc/html/rfc6986.html RFC 6986\r
Streebog must be big-endian serialised.
"streebog256", "streebog512" algorithm identifiers are used.
-=> https://datatracker.ietf.org/doc/html/rfc6986.html RFC 6986\r
[cm/hashed/] with XXH3-128.
+=> https://xxhash.com/ XXH3\r
128-bit XXH3 hash must be big-endian encoded.
"xxh3-128" algorithm identifier is used.
-=> https://xxhash.com/ XXH3\r
-Balloon-BLAKE2b+HKDF KEM.
+Balloon-BLAKE2b + HKDF KEM.
+=> https://crypto.stanford.edu/balloon/ Balloon\r
+=> https://datatracker.ietf.org/doc/html/rfc7693.html RFC 7693, BLAKE2b\r
+=> https://datatracker.ietf.org/doc/html/rfc5869.html RFC 5869, HKDF\r
<< [schemas/kem-balloon-blake2b-hkdf.tcl]\r
-Balloon memory-hardened password hasher must be used with BLAKE2b hash.
-=> https://crypto.stanford.edu/balloon/ Balloon\r
-
H = BLAKE2b
KEK = HKDF-Expand(H,
- prk=balloon(H, passphrase, /kem/salt, s, t, p),
+ prk=Balloon(H, passphrase, /kem/salt, s, t, p),
info="cm/encrypted/balloon-blake2b-hkdf" || /id)
"/kem/*/cek" is wrapped with [cm/keywrap/xchapoly] mechanism.
-=> https://datatracker.ietf.org/doc/html/rfc5869.html RFC 5869, HKDF\r
-=> https://www.blake2.net/ BLAKE2b is hashing algorithm\r
-=> https://datatracker.ietf.org/doc/html/rfc7693.html RFC 7693, same\r
-GOST R 34.10+HKDF KEM.
+GOST R 34.10 + HKDF KEM.
+=> https://datatracker.ietf.org/doc/html/rfc7091.html RFC 7091, GOST R 34.10-2012\r
+=> https://datatracker.ietf.org/doc/html/rfc5869.html RFC 5869, HKDF\r
+=> https://datatracker.ietf.org/doc/html/rfc6986.html RFC 6986, Streebog, GOST R 34.11-2012\r
<< [schemas/kem-gost3410-hkdf.tcl]\r
+Recipient public key with [cm/pub/gost3410] algorithm must be used.
+It should have "kem" key usage set.
+
GOST R 34.10-2012 VKO parameter set A/C ("gost3410-256A", "gost3410-512C")
must be used for DH operation, with UKM taken from the structure. VKO's
output is 512- or 1024-bit "BE(X)||BE(Y)" point, used in HKDF below:
H = Streebog-512
DH(sk, pk) = GOSTR3410-VKO(prv=sk, pub=pk, ukm=UKM)
PRK = HKDF-Extract(H, salt="", ikm=DH(e, s))
- if specified(sender):
+ if {specified sender}
PRK = HKDF-Extract(H, salt=PRK, ikm=DH(s, s))
KEK = HKDF-Expand(H, prk=PRK, info="cm/encrypted/gost3410-hkdf" || /id)
"/kem/*/cek" is wrapped with [cm/keywrap/kexp15] mechanism.
-=> https://datatracker.ietf.org/doc/html/rfc5869.html RFC 5869, HKDF\r
-=> https://datatracker.ietf.org/doc/html/rfc6986.html RFC 6986, Streebog, GOST R 34.11-2012 hashing algorithm\r
-=> https://datatracker.ietf.org/doc/html/rfc7091.html RFC 7091, GOST R 34.10-2012 is signing/key-aggreement algorithm\r
-Classic McEliece 6960-119+X25519+HKDF-SHAKE256 KEM.
+Classic McEliece 6960-119 + X25519 + HKDF-SHAKE256 KEM.
+=> https://classic.mceliece.org/ Classic McEliece\r
+=> https://datatracker.ietf.org/doc/html/rfc7748 X25519\r
+=> https://datatracker.ietf.org/doc/html/rfc5869.html RFC 5869, HKDF\r
+=> https://keccak.team/ SHAKE XOF function\r
<< [schemas/kem-with-encap.tcl]\r
Recipient public key with [cm/pub/mceliece6960119-x25519]
algorithm must be used. It should have "kem" key usage set.
-Recipient's map "/kem/*/encap" field is a concatenation of
-194 bytes of Classic McEliece 6960-119 ciphertext, containing
-ephemeral key, with 32 bytes of ephemeral X25519 public key.
+"/kem/*/encap" field is a concatenation of 194 bytes of
+Classic McEliece 6960-119 ciphertext, containing ephemeral key,
+with 32 bytes of ephemeral X25519 public key.
Recipient performs X25519 and Classic McEliece computations to
derive/decapsulate two 32-byte shared keys. Then it combines
mceliece6960119-shared-key || es-x25519-shared-key ||
H(mceliece6960119-sender-ciphertext || e-x25519-sender-public-key) ||
H(mceliece6960119-recipient-public-key || s-x25519-recipient-public-key))
- if specified(sender):
+ if {specified sender}
PRK = HKDF-Extract(H, salt=PRK, ikm=
ss-x25519-shared-key ||
s-x25519-sender-public-key ||
s-x25519-recipient-public-key)
KEK = HKDF-Expand(H, prk=PRK,
- info="cm/encrypted/mceliece6960119-x25519-hkdf-shake256" || /salt)
+ info="cm/encrypted/mceliece6960119-x25519-hkdf-shake256" || /id)
"/kem/*/cek" is wrapped with [cm/keywrap/xchapoly] mechanism.
-=> https://datatracker.ietf.org/doc/html/rfc5869.html RFC 5869, HKDF\r
-=> https://keccak.team/ SHAKE XOF function\r
KEM combiner nearly fully resembles:
=> https://datatracker.ietf.org/doc/draft-josefsson-chempat/ Chempat\r
PBKDF2 KEM.
+=> https://datatracker.ietf.org/doc/html/rfc2898 RFC 2898, PBKDF2\r
<< [schemas/kem-pbkdf2.tcl]\r
-PBKDF2 is RFC 2898 algorithm.
-Key length equal to key wrapping algorithm requirements.
-=> https://datatracker.ietf.org/doc/html/rfc2898 RFC 2898\r
-
Key wrapping algorithm may be one of:
[cm/keywrap/xchapoly], [cm/keywrap/kexp15],
depending on the hash chosen.
-SNTRUP4591761+X25519+HKDF-BLAKE2b KEM.
+Streamlined NTRU Prime 4591^761 + X25519 + HKDF-BLAKE2b KEM.
+=> https://ntruprime.cr.yp.to/ Streamlined NTRU Prime KEM algorithm\r
+=> https://datatracker.ietf.org/doc/html/rfc7748 X25519\r
+=> https://datatracker.ietf.org/doc/html/rfc5869.html RFC 5869, HKDF\r
+=> https://datatracker.ietf.org/doc/html/rfc7693.html RFC 7693, BLAKE2b\r
<< [schemas/kem-with-encap.tcl]\r
sntrup4591761-shared-key || es-x25519-shared-key ||
H(sntrup4591761-sender-ciphertext || e-x25519-sender-public-key) ||
H(sntrup4591761-recipient-public-key || s-x25519-recipient-public-key))
- if specified(sender):
+ if {specified sender}
PRK = HKDF-Extract(H, salt=PRK, ikm=
ss-x25519-shared-key ||
s-x25519-sender-public-key ||
KExp15(Kenc, Kauth, IV, CEK) = Kuznechik-CTR(
Kenc, CEK || Kuznechik-CMAC(Kauth, IV || CEK), IV=IV)
-Kuznechik is GOST R 34.12-2015 encryption algorithm, RFC 7801.
-=> https://datatracker.ietf.org/doc/html/rfc7801.html RFC 7801\r
+=> https://datatracker.ietf.org/doc/html/rfc7801.html RFC 7801, Kuznechik, GOST R 34.12-2015 \r
CMAC (OMAC1) is described in GOST R 34.13-2015.
XChaCha20-Poly1305 key wrapping mechanism.
Key is encrypted using XChaCha20-Poly1305 algorithm.
+=> https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-xchacha XChaCha20-Poly1305\r
Random 192-bit nonce is prepended to the ciphertext.
KEK has 256-bit length.
-[cm/prv/] with Classic McEliece 6960-119+X25519.
+[cm/prv/] with Classic McEliece 6960-119 + X25519.
+=> https://classic.mceliece.org/ Classic McEliece\r
+=> https://datatracker.ietf.org/doc/html/rfc7748 X25519\r
Concatenation of Classic McEliece 6960-119 13948-byte private key
and X25519's 32-byte one.
"mceliece6960119-x25519" algorithm identifier is used.
-[cm/prv/] with SNTRUP4591761+X25519.
-Concatenation of Streamlined NTRU Prime 4591^761's 1600-byte private key
-and X25519's 32-byte one.
+[cm/prv/] with Streamlined NTRU Prime 4591^761 + X25519.
+=> https://ntruprime.cr.yp.to/ NTRU Prime\r
+=> https://datatracker.ietf.org/doc/html/rfc7748 X25519\r
+It is a concatenation of SNTRUP's 1600-byte and X25519's 32-byte keys.
"sntrup4591761-x25519" algorithm identifier is used.
[cm/prv/] with SPHINCS+-SHAKE256-256s.
-255-bit security level, fast variant and simple parameters.
+255-bit security level, small variant and simple parameters.
=> https://sphincs.org/ SPHINCS+\r
=> https://keccak.team/ SHAKE256\r
Value is concatenation of private and public keys (128+64 bytes).
-Algorithm identifier for the public key: "sphincs+-shake-256s".
+"sphincs+-shake-256s" algorithm identifier is used.
Public key's fingerprint should be calculated using BLAKE2b hash
with 256 bit output length specified.
+=> https://datatracker.ietf.org/doc/html/rfc7693.html RFC 7693, BLAKE2b\r
Algorithm identifier for the public key: "ed25519-blake2b".
-
-=> https://cr.yp.to/ecdh.html X2559, key-agreement algorithm\r
-=> https://datatracker.ietf.org/doc/html/rfc7748.html RFC 7748, same\r
-=> https://www.blake2.net/ BLAKE2b hashing algorithm\r
-=> https://datatracker.ietf.org/doc/html/rfc7693.html RFC 7693, same\r
-[cm/pub/] with GOST R 34.10-2012.
-
-GOST R 34.10-2012 must be used with Streebog (GOST R 34.11-2012)
-hash function. Its digest must be big-endian serialised. Public key
-must be in "BE(X)||BE(Y)" format.
-
+[cm/pub/] with GOST R 34.10-2012 ([cm/signed/gost3410]).
+Public key must be in "BE(X)||BE(Y)" format.
Algorithm identifiers for the public key: "gost3410-256A", "gost3410-512C".
-
-Public key's fingerprint should be calculated using big-endian Streebog-256 hash.
-
-Streebog is GOST R 34.11-2012 hashing algorithm.
-GOST R 34.10-2012 is signing/key-aggreement algorithm.
-=> https://datatracker.ietf.org/doc/html/rfc6986.html RFC 6986, GOST R 34.11-2012\r
-=> https://datatracker.ietf.org/doc/html/rfc7091.html RFC 7091, GOST R 34.10-2012\r
+Public key's fingerprint should be calculated using big-endian Streebog-256.
sub:
Subject is a map of arbitrary strings. Currently no constraints on
- what fields must be present. Each application and usage context
- defines it on his own. But you may mimic X.509's subject with keys
- like "CN", "C", "O" and similar ones.
+ what fields must be present. Each application defines them on its
+ own. But you may mimic X.509's subject with keys like "CN", "C", "O"
+ and similar ones.
pub:
Public key container itself may contain multiple public keys.
That is *solely* intended for tasks requiring more than single
key usage. For example NNCP uses one X25519 for (DH) encryption, one
- curve25519 for online authentication and one ed25519 for signing
- purposes. All those three keys are used together. That public key's
- key usage field must contain something like "nncp".
+ X25519 for online authentication and one ed25519 for signing purposes.
+ All those three keys are used together. That public key's key usage
+ field should contain something like "nncp".
=> http://www.nncpgo.org NNCP\r
If your keypair is intended for general purposes like signing of
- arbitrary data, then single public key @strong{should} be used, with
- a key usage like "sig".
+ arbitrary data, then single public key *should* be used, with a key
+ usage like "sig".
id:
Public key(s)'s fingerprint *should* be generated as 256-bit
- hash hash of the encoded "pub" field. If not stated otherwise
- for specific algorithm.
+ hash over the encoded "pub" field, if not stated otherwise for
+ specific algorithm. Exact hash algorithm depends on the public keys.
ku:
Intended public key(s) usage.
Application-specific example with multiple public keys is described
ones may be placed outside that map, directly in cm/pub/load.
It *must* be absent if empty. Values are extension specific.
-[cm/signed/]'s "sig-tbs" *must* contain additional fields:
+[cm/signed/]'s "tbs" *must* contain additional fields:
<< [schemas/pub-sig-tbs.tcl]\r
cid: Certification unique identifier. UUIDv7 is a good choice.
But it may be UUIDv4, or any desired method of generation.
exp: Certification expiration period.
- It *must* contain TAI64 datetime (no nanoseconds).
Example minimal certified public key may look like:
-[cm/pub/] with Classic McEliece 6960-119+X25519.
+[cm/pub/] with Classic McEliece 6960-119 + X25519.
+=> https://classic.mceliece.org/ Classic McEliece\r
+=> https://datatracker.ietf.org/doc/html/rfc7748 X25519\r
Combined Classic McEliece 6960-119 and X25519 public keys are used
for KEM purposes, so should have "kem" key usage set.
-Its algorithm identifier is "mceliece6960119-x25519". Its
-public key value is a concatenation of 1047319-byte
+Its algorithm identifier is "mceliece6960119-x25519".
+Its public key value is a concatenation of 1047319-byte
mceliece6960119 public key and 32-byte X25519 one.
Public key's fingerprint should be calculated using SHAKE128.
-
-=> https://cr.yp.to/ecdh.html X2559 key-agreement algorithm\r
-=> https://datatracker.ietf.org/doc/html/rfc7748.html RFC 7748, same\r
-=> https://classic.mceliece.org/ Classic McEliece KEM algorithm\r
=> https://keccak.team/ SHAKE XOF function\r
Optional "/load/v/prehash" field can contain the SHAKE256 hash
-[cm/pub/] with SNTRUP4591761+X25519.
+[cm/pub/] with Streamlined NTRU Prime 4591^761 + X25519.
+=> https://ntruprime.cr.yp.to/ Streamlined NTRU Prime KEM algorithm\r
+=> https://datatracker.ietf.org/doc/html/rfc7748 X25519\r
Combined Streamlined NTRU Prime 4591^761 and X25519 public keys are
used for KEM purposes, so should have "kem" key usage set.
-Its algorithm identifier is "sntrup4591761-x25519". Its public
-key value is a concatenation of 1218-byte SNTRUP4591761 public key
-and 32-byte X25519 one.
+Its algorithm identifier is "sntrup4591761-x25519".
+Its public key value is a concatenation of 1218-byte
+SNTRUP4591761 public key and 32-byte X25519 one.
Public key's fingerprint should be calculated using BLAKE2b hash
with 256 bit output length specified.
-
-=> https://cr.yp.to/ecdh.html X2559, key-agreement algorithm\r
-=> https://datatracker.ietf.org/doc/html/rfc7748.html RFC 7748, same\r
-=> https://ntruprime.cr.yp.to/ Streamlined NTRU Prime KEM algorithm\r
+=> https://datatracker.ietf.org/doc/html/rfc7693.html RFC 7693, BLAKE2b\r
[cm/pub/] with SPHINCS+-SHAKE256-256s.
-255-bit security level, fast variant and simple parameters.
+255-bit security level, small variant and simple parameters.
=> https://sphincs.org/ SPHINCS+\r
=> https://keccak.team/ SHAKE256\r
"sphincs+-shake-256s" algorithm identifier is used.
EdDSA with Edwards25519 is used similarly as in RFC 8032.
But BLAKE2b is used instead of SHA2-512 hash.
-Strict ZIP-0215 validation rules should be used while verifying the signature.
-
=> https://datatracker.ietf.org/doc/html/rfc8032 RFC 8032, EdDSA\r
+
+Strict ZIP-0215 validation rules should be used while verifying the signature.
=> https://zips.z.cash/zip-0215 ZIP-0215\r
-PureEdDSA *must" be used when no detached data exists and
-"ed25519-blake2b" algorithm identifier is used for signature.
+PureEdDSA *must* be used when no detached data exists and
+"ed25519-blake2b" algorithm identifier is used in signature.
-HashEdDSA *must" be used otherwise, using BLAKE2b-512 as a
+HashEdDSA *must* be used otherwise, using BLAKE2b-512 as a
hash, using "ed25519ph-blake2b" algorithm identifier for
signature.
[cm/signed/] with Ed25519-BLAKE2b with Merkle-tree hashing.
-[cm/hashed/blake2b-merkle] hashing is used.
-HashEdDSA mode is used with "ed25519ph-blake2b-merkle"
-algorithm identifier for signature.
+
+It is similar to [cm/signed/ed25519-blake2b], but
+HashEdDSA mode is used with [cm/hashed/blake2b-merkle] hashing.
+
+"ed25519ph-blake2b-merkle" algorithm identifier is used in signature.
[cm/signed/] with GOST R 34.10-2012.
+=> https://datatracker.ietf.org/doc/html/rfc7091.html RFC 7091, GOST R 34.10-2012\r
GOST R 34.10-2012 must be used with Streebog (GOST R 34.11-2012)
hash function. Its digest must be big-endian serialised. Signature
is in "BE(R)||BE(S)" format.
+=> https://datatracker.ietf.org/doc/html/rfc6986.html RFC 6986, GOST R 34.11-2012\r
Algorithm identifiers for the signature: "gost3410-256A", "gost3410-512C".
-
-Streebog is GOST R 34.11-2012 hashing algorithm.
-GOST R 34.10-2012 is signing/key-aggreement algorithm.
-=> https://datatracker.ietf.org/doc/html/rfc6986.html RFC 6986, GOST R 34.11-2012\r
-=> https://datatracker.ietf.org/doc/html/rfc7091.html RFC 7091, GOST R 34.10-2012\r
[cm/signed/] with GOST R 34.10-2012 with Merkle-tree hashing.
-[cm/hashed/streebog-merkle] hashing is used.
+
+It is similar to [cm/signed/gost3410], but [cm/hashed/streebog-merkle]
+hashing is used.
+
Algorithm identifiers for the signature:
"gost3410-256A-merkle", "gost3410-512C-merkle".
Stored in a file, it should begin with "cm/signed" [encoding/MAGIC],
unless it is a [cm/pub/]lic key.
+<< [schemas/signed.tcl]\r
<< [schemas/av.tcl]\r
<< [schemas/fpr.tcl]\r
-<< [schemas/signed.tcl]\r
Signature is created by signing the:
[detached-data] || /load || sig-tbs
If no "/load/v" is provided, then the data is detached from the
-"cm/signed" structure itself and it is fed into hasher before that
-structure. You can provide it any way you wish, but for keeping that
-detached data closely to the "cm/signed", you should use the
+"cm/signed" structure itself and is fed into hasher before that
+structure. You can provide it any way you wish, but for keeping
+that detached data closely to the "cm/signed", you should use the
following approach:
- cm/signed/prehash || BLOB(detached-data) || cm/signed
+ prehash || BLOB(detached-data) || cm/signed
<< [schemas/signed-prehash.tcl]\r
-With "cm/signed/prehash" you initialise your hashers used during signing
-process and feed BLOB's contents (not the encoded BLOB itself!) into the them.
+With "prehash" you initialise your hashers used during signing process
+and feed BLOB's contents (not the encoded BLOB itself!) into the them.
"/sigs/*/tbs/when" is optional signing time.
[cm/signed/] with SPHINCS+-SHAKE256-256s.
-255-bit security level, fast variant,
-simple parameters and deterministic signatures.
+255-bit security level, small variant, simple parameters.
=> https://sphincs.org/ SPHINCS+\r
=> https://keccak.team/ SHAKE256\r
+
"sphincs+-shake-256s" algorithm identifier
must be used for the signature in pure signing mode.
"sphincs+-shake-256s-ph" is used in prehash mode.
[cm/signed/] with SPHINCS+-SHAKE256-256s with Merkle-tree hashing.
+
+It is similar to [cm/signed/sphincs+-shake-256s], but
[cm/hashed/shake-merkle] SHAKE256 Merkle-tree hashing is used.
-"sphincs+-shake-256s-merkle" algorithm identifier must be used for the signature.
+
+"sphincs+-shake-256s-merkle" algorithm identifier is used for the signature.
021 | 15 | 00010101 | 0 |
022 | 16 | 00010110 | 0 |
023 | 17 | 00010111 | 0 |
-024 | 18 | 00011000 | 8 | [encoding/TAI64]
-025 | 19 | 00011001 | 12 | [encoding/TAI64] N
-026 | 1A | 00011010 | 16 | [encoding/TAI64] NA
+024 | 18 | 00011000 | 8 | [encoding/TAI]64
+025 | 19 | 00011001 | 12 | [encoding/TAI]64N
+026 | 1A | 00011010 | 16 | [encoding/TAI]64NA
027 | 1B | 00011011 | 0 |
028 | 1C | 00011100 | 0 |
029 | 1D | 00011101 | 0 |
-Integers are encoded as ordinary binary [encoding/String], that has
-prepended byte indicating is it positive or negative integer.
+Integers are encoded as ordinary binary big-endian [encoding/String],
+that has prepended byte indicating is it positive or negative integer.
-Negative integers store their absolute value the same way as positive
-integers. After decoding, their value is subtracted from -1. Negative
-value encoded as 0x02 means: -1 - 0x02 => -3.
+Negative integers store positive absolute value, minus one.
+After decoding, their value is subtracted from -1.
+Negative value encoded as 0x02 means: -1 - 0x02 => -3.
Shortest possible form *must* be used, that means no leading zero
byte. 0 and -1 values are empty strings, so even they won't have
-MAP contains concatenation of string(key)-value pairs.
-Keys *must* be non-empty, unique and length-first bytewise ascending ordered.
+MAP contains concatenation of [encoding/String](key)⇔value pairs.
MAP [STR(KEY0) || ITEM0 || STR(KEY1) || ITEM1 || ...] EOC
+Keys *must* be non-empty, unique and length-first bytewise ascending ordered.
+
Hint: Encoding code for known format can be ordered itself to emit
values in an already properly sorted way.
-There are two kinds of strings: binary (STR) and
-UTF-8 (human-readable ones, STR).
+There are two kinds of strings:
+BIN (binary) and STR (human-readable, printable ones).
-Most significant tag's bit is set for them. Seventh bit tells is it
-UTF-8 string, binary otherwise. Next six bits contain the length of
-the string.
+Most significant tag's bit is set. Seventh bit tells is it UTF-8 string,
+binary otherwise. Next six bits contain the length of the string.
len
+------+
If length value equals to:
0-60 => Use as is.
61 => 61 + next 8-bits value.
-62 => 62 + 255 + next big-endian 16-bits value.
-63 => 63 + 255 + 65535 + next big-endian 64-bits value.
+62 => 62 + 255 + next big-endian 16-bit value.
+63 => 63 + 255 + 65535 + next big-endian 64-bit value.
String's length *must* be encoded in shortest possible form.
Example representations:
-0-byte binary string => 80
-4-byte binary string 0x01 0x02 0x03 0x04 => 84 01 02 03 04
-64-byte binary string with 0x41 => BD 03 41 41 ... 41
-UTF-8 string "привет мир" ("hello world" in russian) =>
- D3 D0 BF D1 80 D0 B8 D0 B2 D0 B5 D1 82 20 D0 BC D0 B8 D1 80
+BIN "" | 80
+BIN [binary decode hex "01 02 03 04"] | 84 01 02 03 04
+BIN [string repeat "A" 64] | BD 03 41 41 ... 41
+
+STR "hello world" | CB 68656C6C6F 20 776F726C64
+STR "привет мир" | D3 D0BFD180D0B8D0B2D0B5D182 20 D0BCD0B8D180
Datetime is represented in, so called, external TAI64 format.
+=> http://cr.yp.to/libtai/tai64.html TAI64\r
TAI stands for Temps Atomique International, the current international
real time standard. Unlike UTC, it takes leap seconds into account,
making it monotonous.
-
-=> http://cr.yp.to/libtai/tai64.html TAI64\r
=> http://cr.yp.to/proto/utctai.html TAI\r
-You can convert TAI to UTC by subtracting number of leap seconds.
+You can convert UTC to TAI by adding the number of leap seconds.
-TAI64N format adds 32-bit big-endian number of nanoseconds
-(up to 999999999) count.
-TAI64NA adds another 32-big big-endian part of attoseconds count.
+External TAI64 format is big-endian 64-bit number of TAI seconds passed
+since 1970-01-01, plus 1<<62. TAI64N format adds 32-bit big-endian
+number of nanoseconds (up to 999999999). TAI64NA adds another 32-big
+big-endian part of attoseconds.
Shortest form *must* be used: if number of nanoseconds equals to zero,
then use TAI64 format.
019 | 13 | 00010011 | 16 | [encoding/FLOAT] 128
020 | 14 | 00010100 | 32 | [encoding/FLOAT] 256
... | ... | ... | ... | ...
-024 | 18 | 00011000 | 8 | [encoding/TAI64]
-025 | 19 | 00011001 | 12 | [encoding/TAI64] N
-026 | 1A | 00011010 | 16 | [encoding/TAI64] NA
+024 | 18 | 00011000 | 8 | [encoding/TAI]64
+025 | 19 | 00011001 | 12 | [encoding/TAI]64N
+026 | 1A | 00011010 | 16 | [encoding/TAI]64NA
... | ... | ... | ... | ...
075 | 4B | 01001011 | 15 | [encoding/MAGIC]
... | ... | ... | ... | ...
following elements are command-specific.
Here is full list of structure validation commands, that should be
-generated from higher level schema descriptions. Here comes human
-readable command name, its string byte-code and possible arguments.
+generated from higher level schema descriptions.
-TAKE | "." | args: k
+TAKE | [".", k]
Take/choose the value of the "k" key in the map, if "k" is a string.
If "k" is integer, then choose the k-th value in a list.
If "k" equals to ".", then choose the element you are currently in.
Command never fails, but key can be non-existent.
-EXISTS | "E"
+EXISTS | ["E"]
Assure that chosen element exists.
-!EXISTS | "!E"
+!EXISTS | ["!E"]
Assure that chosen element does not exist.
-EACH | "*"
+EACH | ["*"]
Execute the next command against every element of the chosen
(if it exists) list, or every value of the map.
-TYPE | "T" | args: T0 [T1 ...]
+TYPE | ["T", T0 [, T1, ...]]
Check that chosen (if it exists) element's type is in (T0, T1 ...)
- set. Possible types: BIN, BLOB, BOOL, HEXLET, INT, LIST, MAGIC, MAP,
- NIL, STR, TAI.
+ set. Possible types: "BIN", "BLOB", "BOOL", "HEXLET", "INT", "LIST",
+ "MAGIC", "MAP", "NIL", "STR", "TAI".
-GT | ">" | args: n
+GT | [">", n]
Check that chosen (if it exists) integer value is greater than "n".
If chosen value is either list or map, then check their length.
If the value is a string, then check its length.
-LT | "<" | args: n
+LT | ["<", n]
Same as ">", but check that value is less than "n".
-SCHEMA | "S" | args: s
+SCHEMA | ["S", s]
Check chosen (if it exists) element against schema named "s".
-TIMEPREC | "TP" | args: p
+TIMEPREC | ["TP", p]
Check that chosen (if it exists) element, of time type, has value of
maximal specified time precision. "p" is integer with following
possible values:
15: only up to femtoseconds;
18: up to attoseconds;
-UTC | "UTC"
- Check that chosen (if it exists) element, of time type,
+UTC | ["UTC"]
+ Check that chosen (if it exists) element, of TAI type,
can be converted to UTC.
-EQ | "=" | args: v
+EQ | ["=", v]
Check that chosen (if it exists) element's value equals to binary
string "v".
["T", "STR"],
]}
-Here is example with multiple schemas:
+Here is an example with multiple schemas:
latitude = -90..90
longitude = -180..180
["<", 3],
[".", "."],
["*"],
- [".", "INT"],
+ ["T", "INT"],
[".", 0],
[">", -91],
[".", 0],
So suggestion is to specify those steps for some kind of very simple
minimalistic validation machine, that interprets them, executing
-validation commands against the provided data structures. That "machine"
-should be simple enough to be able to implement it quickly and with sane
-amount of code. Validation steps should be easily decodable and
-conveniently parsed even in C-language.
+validation commands ([schema/cmds]) against the provided data
+structures. That "machine" should be simple enough to be able to
+implement it quickly and with sane amount of code. Validation steps
+should be easily decodable and conveniently parsed even in C-language.
Let's use KEKS format itself for the serialised validation steps! And
-generate them from higher level language/code, convenient for humans.
+generate them from higher level language/code ([schema/tcl]), convenient
+for humans.
- cmds = KEKS-Encode([schema/tcl] -> [schema/cmds])
- validate(KEKS-Decode(cmds), KEKS-Decode(data))
+ [schema/tcl] -> [schema/cmds] -> keks-encode() => schema
+ validate(schema, keks-decode(data))
Validation commands are pretty low-level and are inconvenient to write
by hand, at least because of huge quantity of TAKEs.
tcl/schema.tcl utility gives ability to convert much more nicer schemas
-written on Tcl language to the KEKS-encoded commands. We call that
-Tcl-written schemas KEKS/Schema.
+written on Tcl language to the KEKS-encoded commands. We call those
+Tcl-written schemas "KEKS/Schema".
Example with "our" structure ([schema/cmds]) can be written as:
<< [schemas/pub-load.tcl]\r
<< [schemas/pub-sig-tbs.tcl]\r
-schema.tcl calls "schemas {s0 cmds0 s1 cmds1 ...}"
-commands to produce an encoded map with "cmds*" commands for
-"s*" schemas. There is "field" command that helps creation of
-commands related to the field.
+schema.tcl calls "schemas {s0 cmds0 s1 cmds1 ...}" commands to produce
+an encoded map with "cmds*" commands for "s*" schemas.
+
+"field" command helps creation of commands related to the field.
Its first argument is either field's name in the map, or list's index or
dot, meaning the self-structure itself.
element has specified string/binary value (use "len=" for integers).
"prec=p" issues TIMEPREC command, but instead of specifying the raw
-integer values, you choose one of: s, ms, us, ns, ps, fs, as. "utc"
-issues UTC command.
+integer values, you choose one of: s, ms, us, ns, ps, fs, as.
+"utc" issues UTC command.
"of s" argument issues checking of EACH element of the list or map
against the specified schema, or against specified type if "s" is a
load {
{field . {map}}
{field t {str} >0}
+ {# field v is optional, arbitrary type}
}
sig {