]> Cypherpunks repositories - keks.git/commitdiff
Various refactoring and passphrase-encrypted private keys support
authorSergey Matveev <stargrave@stargrave.org>
Sun, 16 Feb 2025 07:02:58 +0000 (10:02 +0300)
committerSergey Matveev <stargrave@stargrave.org>
Mon, 17 Feb 2025 16:34:36 +0000 (19:34 +0300)
31 files changed:
c/cmd/pp/pp.c
go/.gitignore [new file with mode: 0644]
go/cm/.gitignore [new file with mode: 0644]
go/cm/cmd/enctool/main.go
go/cm/cmd/enctool/passphrase.t
go/cm/cmd/enctool/prv-encrypted.t [new file with mode: 0755]
go/cm/cmd/enctool/pub.t
go/cm/cmd/hshtool/main.go
go/cm/cmd/keytool/certification.t
go/cm/cmd/keytool/kem-generation.t
go/cm/cmd/sigtool/basic.t
go/cm/enc/balloon.go [deleted file]
go/cm/enc/balloon/cost/cost.go [new file with mode: 0644]
go/cm/enc/balloon/decap.go [new file with mode: 0644]
go/cm/enc/chapoly/dem.go
go/cm/enc/dem.go
go/cm/enc/enc.go [new file with mode: 0644]
go/cm/enc/kem.go
go/cm/go.mod
go/cm/hash/hash.go [new file with mode: 0644]
go/cm/utils/mk-bin [new file with mode: 0755]
go/cmd/pp/go.mod [new file with mode: 0644]
go/cmd/pp/go.sum [new file with mode: 0644]
go/cmd/pp/main.go
go/go.mod
go/go.sum
go/utils/mk-bin [new file with mode: 0755]
spec/cm/encrypted.cddl
spec/cm/encrypted.texi
spec/cm/hashed.cddl
spec/cm/hashed.texi

index 3b5f2534025ec3212b12f20fbdeb05b0fecccc476afa0e2a48cc57b1eff05811..ea68877cd230e74927c8dfd9d7fdd12c9ef63d8c52e6c0b1429e113c5a63d02e 100644 (file)
@@ -44,7 +44,7 @@ static char *ColourCyan = "\x1b[36m";
 static char *ColourWhite = "\x1b[37m";
 static char *ColourReset = "\x1b[0m";
 
-static size_t MaxStrLen = 40;
+static size_t MaxStrLen = 64;
 static bool NoOffsets = false;
 static int OffDigits = 0;
 static char OffFmt[16] = {0};
diff --git a/go/.gitignore b/go/.gitignore
new file mode 100644 (file)
index 0000000..0d4fc74
--- /dev/null
@@ -0,0 +1 @@
+bin/
diff --git a/go/cm/.gitignore b/go/cm/.gitignore
new file mode 100644 (file)
index 0000000..0d4fc74
--- /dev/null
@@ -0,0 +1 @@
+bin/
index 3c1aaa29ae0533701047487546fbbbf463cd38b73707423f0cc6a3c48b90f278..4910826b56905b0b7927e1e252ba7a9fedf8665cea29ce0c68dbd306b4a2a2ac 100644 (file)
@@ -28,6 +28,7 @@ import (
        "log"
        "os"
        "runtime"
+       "strconv"
 
        "github.com/companyzero/sntrup4591761"
        "github.com/google/uuid"
@@ -38,6 +39,8 @@ import (
        "go.cypherpunks.su/keks"
        "go.cypherpunks.su/keks/cm"
        cmenc "go.cypherpunks.su/keks/cm/enc"
+       cmballoon "go.cypherpunks.su/keks/cm/enc/balloon"
+       ballooncost "go.cypherpunks.su/keks/cm/enc/balloon/cost"
        chaPoly "go.cypherpunks.su/keks/cm/enc/chapoly"
        mceliece6960119x25519 "go.cypherpunks.su/keks/cm/enc/mceliece6960119-x25519"
        mceliece6960119 "go.cypherpunks.su/keks/cm/enc/mceliece6960119-x25519/mceliece6960119"
@@ -87,17 +90,68 @@ func readPasswd(prompt string) (passwd []byte) {
        return
 }
 
+func readPrv(pth string) (*cm.AV, error) {
+       data := mustReadFile(pth)
+       var magic keks.Magic
+       magic, data = keks.StripMagic(data)
+       switch magic {
+       case sign.PrvMagic:
+       case cmenc.Magic:
+               var encrypted cmenc.Encrypted
+               {
+                       d := keks.NewDecoderFromBytes(data, nil)
+                       if err := d.DecodeStruct(&encrypted); err != nil {
+                               return nil, err
+                       }
+               }
+               if encrypted.DEM.A != cmenc.ChaCha20Poly1305 {
+                       return nil, errors.New("unsupported prv encryption DEM")
+               }
+               if len(encrypted.KEM) != 1 ||
+                       encrypted.KEM[0].A != cmballoon.BalloonBLAKE2bHKDF ||
+                       len(encrypted.Payload) == 0 {
+                       return nil, errors.New("wrong prv encryption KEM")
+               }
+               passwd := readPasswd("Passphrase for " + pth + ":")
+               cek, err := cmballoon.Decapsulate(
+                       encrypted.KEM[0],
+                       encrypted.Salt[:],
+                       passwd,
+               )
+               if err != nil {
+                       return nil, err
+               }
+               var buf bytes.Buffer
+               _, err = chaPoly.Open(&buf, bytes.NewReader(encrypted.Payload), cek, 1)
+               if err != nil {
+                       return nil, err
+               }
+               data = buf.Bytes()
+               magic, data = keks.StripMagic(data)
+               if magic == sign.PrvMagic {
+                       break
+               }
+               fallthrough
+       default:
+               return nil, errors.New("wrong magic")
+       }
+       var av cm.AV
+       d := keks.NewDecoderFromBytes(data, &keks.DecodeOpts{MaxStrLen: 1 << 16})
+       return &av, d.DecodeStruct(&av)
+}
+
 func main() {
        log.SetFlags(log.Lshortfile)
        flag.Usage = usage
        setSalt := flag.String("salt", "", "Set that /salt instead of autogeneration")
        includeTo := flag.Bool("include-to", false, `Include "to" field in KEMs`)
        passphrase := flag.Bool("p", false, "Use passphrase")
-       balloonS := flag.Int("balloon-s", 1<<16, "Balloon's space cost")
-       balloonT := flag.Int("balloon-t", 3, "Balloon's time cost")
+       balloonS := flag.Int("balloon-s", 1<<17, "Balloon's space cost")
+       balloonT := flag.Int("balloon-t", 4, "Balloon's time cost")
        balloonP := flag.Int("balloon-p", 2, "Balloon's number of threads")
        doDecrypt := flag.Bool("d", false, "Decrypt")
        parallel := flag.Int("parallel", runtime.NumCPU(), "Parallel cryptors")
+       noblob := flag.Bool("no-stream", false, "Include payload into container")
        var pubs []*sign.Pub
        flag.Func("pub", "Path to public key to encrypt to", func(v string) error {
                signed, err := sign.PubParse(mustReadFile(v))
@@ -119,18 +173,12 @@ func main() {
                return err
        })
        var prvs []*cm.AV
-       flag.Func("prv", "Our private keys for decryption", func(v string) (err error) {
-               magic, data := keks.StripMagic(mustReadFile(v))
-               if magic == "" || magic != sign.PrvMagic {
-                       return errors.New("wrong magic")
+       flag.Func("prv", "Our private keys for decryption", func(v string) error {
+               av, err := readPrv(v)
+               if err == nil {
+                       prvs = append(prvs, av)
                }
-               var av cm.AV
-               d := keks.NewDecoderFromBytes(data, &keks.DecodeOpts{MaxStrLen: 1 << 16})
-               if err = d.DecodeStruct(&av); err != nil {
-                       return err
-               }
-               prvs = append(prvs, &av)
-               return nil
+               return err
        })
        flag.Parse()
 
@@ -167,45 +215,24 @@ func main() {
                }
                for kemIdx, kem := range encrypted.KEM {
                        switch kem.A {
-                       case cmenc.BalloonBLAKE2bHKDF:
+                       case cmballoon.BalloonBLAKE2bHKDF:
                                if !*passphrase {
                                        log.Println(kemIdx, kem.A, "skipping because no -passwd")
                                        continue
                                }
-                               if kem.Salt == nil {
-                                       log.Fatalln("missing salt")
-                               }
-                               if kem.Cost == nil {
-                                       log.Fatalln("missing cost")
+                               passwd := readPasswd("Passphrase for " + strconv.Itoa(kemIdx) + " KEM:")
+                               cek, err = cmballoon.Decapsulate(
+                                       kem,
+                                       encrypted.Salt[:],
+                                       passwd,
+                               )
+                               if err != nil {
+                                       log.Print(err)
+                                       continue
                                }
-                               passwd := readPasswd("Passphrase:")
-                               {
-                                       var kek []byte
-                                       kek, err = hkdf.Expand(
-                                               blake2bHash,
-                                               balloon.H(
-                                                       blake2bHash,
-                                                       passwd,
-                                                       append(encrypted.Salt[:], *kem.Salt...),
-                                                       int(kem.Cost.S), int(kem.Cost.T), int(kem.Cost.P),
-                                               ),
-                                               cmenc.BalloonHKDFInfo,
-                                               chaPoly.KeyLen,
-                                       )
-                                       if err != nil {
-                                               log.Fatal(err)
-                                       }
-                                       var cekp bytes.Buffer
-                                       _, err = chaPoly.Open(&cekp, bytes.NewReader(kem.CEK), kek, 1)
-                                       if err != nil {
-                                               log.Println(kemIdx, kem.A, err, ", skipping")
-                                               continue
-                                       }
-                                       if cekp.Len() != chaPoly.KeyLen {
-                                               log.Println(kemIdx, kem.A, "wrong key len, skipping")
-                                               continue
-                                       }
-                                       cek = cekp.Bytes()
+                               if len(cek) != chaPoly.KeyLen {
+                                       log.Println(kemIdx, kem.A, "wrong key len, skipping")
+                                       continue
                                }
                        case sntrup4591761x25519.SNTRUP4591761X25519HKDFBLAKE2b:
                                if len(prvs) == 0 {
@@ -397,7 +424,11 @@ func main() {
                if cek == nil {
                        log.Fatal("no KEMs processed")
                }
-               _, err = chaPoly.Open(os.Stdout, os.Stdin, cek, *parallel)
+               if len(encrypted.Payload) > 0 {
+                       _, err = chaPoly.Open(os.Stdout, bytes.NewReader(encrypted.Payload), cek, *parallel)
+               } else {
+                       _, err = chaPoly.OpenBlob(os.Stdout, os.Stdin, cek, *parallel)
+               }
                if err != nil {
                        log.Fatal(err)
                }
@@ -422,12 +453,12 @@ func main() {
                                        log.Fatal("passphrases do not match")
                                }
                        }
-                       bSalt := make([]byte, cmenc.BalloonSaltLen)
+                       bSalt := make([]byte, cmballoon.SaltLen)
                        rand.Read(bSalt)
                        kem := cmenc.KEM{
-                               A:    cmenc.BalloonBLAKE2bHKDF,
+                               A:    cmballoon.BalloonBLAKE2bHKDF,
                                Salt: &bSalt,
-                               Cost: &cmenc.BalloonCost{
+                               BalloonCost: &ballooncost.Cost{
                                        S: uint64(*balloonS),
                                        T: uint64(*balloonT),
                                        P: uint64(*balloonP),
@@ -442,7 +473,7 @@ func main() {
                                                append(salt[:], bSalt...),
                                                *balloonS, *balloonT, *balloonP,
                                        ),
-                                       cmenc.BalloonHKDFInfo,
+                                       cmballoon.HKDFInfo,
                                        chaPoly.KeyLen,
                                )
                                if err != nil {
@@ -606,19 +637,29 @@ func main() {
                        if _, err = keks.Encode(&hdr, cmenc.Magic, nil); err != nil {
                                log.Fatal(err)
                        }
-                       if _, err = keks.Encode(&hdr, &cmenc.Encrypted{
+                       enc := cmenc.Encrypted{
                                Salt: salt,
                                KEM:  kems,
                                DEM:  cmenc.DEM{A: cmenc.ChaCha20Poly1305},
-                       }, nil); err != nil {
+                       }
+                       if *noblob {
+                               var buf bytes.Buffer
+                               if _, err = chaPoly.Seal(&buf, os.Stdin, cek, *parallel); err != nil {
+                                       log.Fatal(err)
+                               }
+                               enc.Payload = buf.Bytes()
+                       }
+                       if _, err = keks.Encode(&hdr, &enc, nil); err != nil {
                                log.Fatal(err)
                        }
                        if _, err = io.Copy(os.Stdout, &hdr); err != nil {
                                log.Fatal(err)
                        }
                }
-               if _, err = chaPoly.Seal(os.Stdout, os.Stdin, cek, *parallel); err != nil {
-                       log.Fatal(err)
+               if !*noblob {
+                       if _, err = chaPoly.SealBlob(os.Stdout, os.Stdin, cek, *parallel); err != nil {
+                               log.Fatal(err)
+                       }
                }
        }
 }
index a1e40c245330e3b64e77b1bd4f8ee269ac6b5e2a2eadacd6a8ce6d81cc3cf70e..66506de3a755c8a829044c83390ea18cc3aac006e211decea7001689113ace1b 100755 (executable)
@@ -1,15 +1,15 @@
 #!/bin/sh
 
-test_description="Check that basic passphrase encryption functionality works"
+test_description="Check passphrase encryption"
 . $SHARNESS_TEST_SRCDIR/sharness.sh
 
 TMPDIR=${TMPDIR:-/tmp}
 
 dd if=/dev/urandom of=$TMPDIR/enc.data bs=300K count=1 2>/dev/null
 export ENCTOOL_PASSPHRASE=$(dd if=/dev/urandom bs=32 count=1 2>/dev/null | xxd -p)
-test_expect_success "encrypting" "enctool -p \
+test_expect_success "encrypting" "cmenctool -p \
     <$TMPDIR/enc.data >$TMPDIR/enc.enc"
-test_expect_success "decrypting" "enctool -d -p \
+test_expect_success "decrypting" "cmenctool -d -p \
     <$TMPDIR/enc.enc >$TMPDIR/enc.data.got"
 test_expect_success "comparing" \
     "test_cmp $TMPDIR/enc.data $TMPDIR/enc.data.got"
diff --git a/go/cm/cmd/enctool/prv-encrypted.t b/go/cm/cmd/enctool/prv-encrypted.t
new file mode 100755 (executable)
index 0000000..dc9ba92
--- /dev/null
@@ -0,0 +1,21 @@
+#!/bin/sh
+
+test_description="Check passphrase-encrypted key decryption"
+. $SHARNESS_TEST_SRCDIR/sharness.sh
+
+TMPDIR=${TMPDIR:-/tmp}
+
+cmkeytool -algo sntrup4591761-x25519 -ku kem -subj A=KEY \
+    -prv $TMPDIR/enc.prv -pub $TMPDIR/enc.pub
+dd if=/dev/urandom of=$TMPDIR/enc.data bs=12K count=1 2>/dev/null
+export ENCTOOL_PASSPHRASE=$(dd if=/dev/urandom bs=32 count=1 2>/dev/null | xxd -p)
+test_expect_success "key encrypting" "cmenctool -p -no-blob \
+    <$TMPDIR/enc.prv >$TMPDIR/enc.prv.enc"
+test_expect_success "data encrypting" "cmenctool -pub $TMPDIR/enc.pub \
+    <$TMPDIR/enc.data >$TMPDIR/enc.enc"
+test_expect_success "decrypting" "cmenctool -d -prv $TMPDIR/enc.prv.enc \
+    <$TMPDIR/enc.enc >$TMPDIR/enc.data.got"
+test_expect_success "comparing" \
+    "test_cmp $TMPDIR/enc.data $TMPDIR/enc.data.got"
+
+test_done
index ec464d6a8bee3ecdb78964be5b94a22923b63dbb46850a4f7fbe6d287965c918..5d7065d64f4c01ff381a6367fcf239b7baf00d8606c64b34fd3fbbd115d63d29 100755 (executable)
@@ -1,6 +1,6 @@
 #!/bin/sh
 
-test_description="Check that basic public-key encryption functionality works"
+test_description="Check public-key encryption"
 . $SHARNESS_TEST_SRCDIR/sharness.sh
 
 TMPDIR=${TMPDIR:-/tmp}
@@ -9,47 +9,47 @@ dd if=/dev/urandom of=$TMPDIR/enc.data bs=300K count=1 2>/dev/null
 
 algo=mceliece6960119-x25519
 algo0=$algo
-test_expect_success "$algo: pub generation" "keytool \
+test_expect_success "$algo: pub generation" "cmkeytool \
     -algo $algo -ku kem -subj A=$algo \
     -prv $TMPDIR/enc.$algo.prv -pub $TMPDIR/enc.$algo.pub"
 algo=sntrup4591761-x25519
 algo1=$algo
-test_expect_success "$algo: pub generation" "keytool \
+test_expect_success "$algo: pub generation" "cmkeytool \
     -algo $algo -ku kem -subj A=$algo \
     -prv $TMPDIR/enc.$algo.prv -pub $TMPDIR/enc.$algo.pub"
 
-test_expect_success "encrypting" "enctool \
+test_expect_success "encrypting" "cmenctool \
     -pub $TMPDIR/enc.$algo0.pub -pub $TMPDIR/enc.$algo1.pub \
     <$TMPDIR/enc.data >$TMPDIR/enc.enc"
 
-test_expect_success "any: decrypting" "enctool -d \
+test_expect_success "any: decrypting" "cmenctool -d \
     -prv $TMPDIR/enc.$algo0.prv -prv $TMPDIR/enc.$algo1.prv \
     <$TMPDIR/enc.enc >$TMPDIR/enc.data.got"
 test_expect_success "comparing" \
     "test_cmp $TMPDIR/enc.data $TMPDIR/enc.data.got"
 
-test_expect_success "$algo0: decrypting" "enctool -d \
+test_expect_success "$algo0: decrypting" "cmenctool -d \
     -prv $TMPDIR/enc.$algo0.prv \
     <$TMPDIR/enc.enc >$TMPDIR/enc.data.got"
 test_expect_success "$algo0: comparing" \
     "test_cmp $TMPDIR/enc.data $TMPDIR/enc.data.got"
 
-test_expect_success "$algo1: decrypting" "enctool -d \
+test_expect_success "$algo1: decrypting" "cmenctool -d \
     -prv $TMPDIR/enc.$algo1.prv \
     <$TMPDIR/enc.enc >$TMPDIR/enc.data.got"
 test_expect_success "$algo1: comparing" \
     "test_cmp $TMPDIR/enc.data $TMPDIR/enc.data.got"
 
 export ENCTOOL_PASSPHRASE=$(dd if=/dev/urandom bs=32 count=1 2>/dev/null | xxd -p)
-test_expect_success "encrypting also with passphrase" "enctool \
+test_expect_success "encrypting also with passphrase" "cmenctool \
     -pub $TMPDIR/enc.$algo0.pub -pub $TMPDIR/enc.$algo1.pub -p \
     <$TMPDIR/enc.data >$TMPDIR/enc.enc"
-test_expect_success "any: decrypting" "enctool -d \
+test_expect_success "any: decrypting" "cmenctool -d \
     -prv $TMPDIR/enc.$algo0.prv -prv $TMPDIR/enc.$algo1.prv \
     <$TMPDIR/enc.enc >$TMPDIR/enc.data.got"
 test_expect_success "comparing" \
     "test_cmp $TMPDIR/enc.data $TMPDIR/enc.data.got"
-test_expect_success "passphrase: decrypting" "enctool -d -p \
+test_expect_success "passphrase: decrypting" "cmenctool -d -p \
     <$TMPDIR/enc.enc >$TMPDIR/enc.data.got"
 test_expect_success "comparing" \
     "test_cmp $TMPDIR/enc.data $TMPDIR/enc.data.got"
index 6c2b9e36939a1193287ed06d900e72ba3abb7ed5ad419d4a014ad58035dc144d..d43cc4b7cb8619d0409d02a6749079e73fac6e1756a2bde164b122cf28dfb957 100644 (file)
@@ -2,7 +2,6 @@ package main
 
 import (
        "crypto/sha512"
-       "encoding/hex"
        "flag"
        "fmt"
        "log"
@@ -11,6 +10,8 @@ import (
 
        "go.cypherpunks.su/gogost/v6/gost34112012256"
        "go.cypherpunks.su/gogost/v6/gost34112012512"
+
+       "go.cypherpunks.su/keks"
        cmhash "go.cypherpunks.su/keks/cm/hash"
        cmblake2b "go.cypherpunks.su/keks/cm/hash/blake2b"
        "go.cypherpunks.su/keks/cm/hash/gost"
@@ -20,7 +21,7 @@ import (
 func main() {
        workers := flag.Int("p", runtime.NumCPU(), "Parallel workers")
        chunkLenK := flag.Int("c", merkle.DefaultChunkLen/1024, "Chunk size, KiB")
-       algo := flag.String("a", cmhash.BLAKE2b, "Algorithm to use")
+       algo := flag.String("a", cmhash.BLAKE2bMerkle, "Algorithm to use")
        list := flag.Bool("list", false, "List available algorithms")
        mmap := flag.String("mmap", "", "Use that mmap-ed file instead of stdin")
        flag.Parse()
@@ -60,5 +61,10 @@ func main() {
        if err != nil {
                log.Fatal(err)
        }
-       fmt.Println(hex.EncodeToString(hasher.Sum(nil)))
+       s := cmhash.Hashed{
+               Algo: []string{*algo},
+               Typ:  "data",
+               Hash: [][]byte{hasher.Sum(nil)},
+       }
+       keks.Encode(os.Stdout, s, nil)
 }
index f2780bb24aac6b4ab20994ac89c49ae9d371c6cab5459e9a1a658c12eac14c16..30f68e9e78237e529acee5832204da07e4739649fb8b4c9f3c70843dda453e5e 100755 (executable)
@@ -1,6 +1,6 @@
 #!/bin/sh
 
-test_description="Check that basic certification functionality works"
+test_description="Check certification"
 . $SHARNESS_TEST_SRCDIR/sharness.sh
 
 TMPDIR=${TMPDIR:-/tmp}
@@ -9,42 +9,42 @@ echo "gost3410-512C gost3410-256A
 ed25519-blake2b ed25519-blake2b" | while read caAlgo eeAlgo ; do
 
 subj="-subj CN=CA -subj C=RU"
-test_expect_success "$caAlgo: CA load generation" "keytool \
+test_expect_success "$caAlgo: CA load generation" "cmkeytool \
     -algo $caAlgo \
     -ku sig $subj \
     -prv $TMPDIR/ca.$caAlgo.prv -pub $TMPDIR/ca.$caAlgo.pub"
-test_expect_success "$caAlgo: CA generation" "keytool \
+test_expect_success "$caAlgo: CA generation" "cmkeytool \
     -pub $TMPDIR/ca.$caAlgo.pub \
     -ca-prv $TMPDIR/ca.$caAlgo.prv -ca-pub $TMPDIR/ca.$caAlgo.pub"
-test_expect_success "$caAlgo: CA regeneration" "keytool \
+test_expect_success "$caAlgo: CA regeneration" "cmkeytool \
     -pub $TMPDIR/ca.$caAlgo.pub \
     -ca-prv $TMPDIR/ca.$caAlgo.prv -ca-pub $TMPDIR/ca.$caAlgo.pub"
-test_expect_success "$caAlgo: CA self-signature" "keytool \
+test_expect_success "$caAlgo: CA self-signature" "cmkeytool \
     -ca-pub $TMPDIR/ca.$caAlgo.pub \
     -pub $TMPDIR/ca.$caAlgo.pub \
     -verify"
 
 subj="-subj CN=SubCA -subj C=RU"
-test_expect_success "$eeAlgo: SubCA load generation" "keytool \
+test_expect_success "$eeAlgo: SubCA load generation" "cmkeytool \
     -algo $eeAlgo \
     -ku sig $subj \
     -prv $TMPDIR/subca.$eeAlgo.prv -pub $TMPDIR/subca.$eeAlgo.pub"
-test_expect_success "$eeAlgo: SubCA generation" "keytool \
+test_expect_success "$eeAlgo: SubCA generation" "cmkeytool \
     -pub $TMPDIR/subca.$eeAlgo.pub \
     -ca-pub $TMPDIR/ca.$caAlgo.pub -ca-prv $TMPDIR/ca.$caAlgo.prv"
-test_expect_success "$eeAlgo: SubCA signature" "keytool \
+test_expect_success "$eeAlgo: SubCA signature" "cmkeytool \
     -ca-pub $TMPDIR/ca.$caAlgo.pub \
     -pub $TMPDIR/subca.$eeAlgo.pub \
     -verify"
 
 subj="-subj CN=EE -subj C=RU"
-test_expect_success "$eeAlgo: EE load generation" "keytool \
+test_expect_success "$eeAlgo: EE load generation" "cmkeytool \
     -algo $eeAlgo $subj \
     -prv $TMPDIR/ee.$eeAlgo.prv -pub $TMPDIR/ee.$eeAlgo.pub"
-test_expect_success "$eeAlgo: EE generation" "keytool \
+test_expect_success "$eeAlgo: EE generation" "cmkeytool \
     -ca-prv $TMPDIR/subca.$eeAlgo.prv -ca-pub $TMPDIR/subca.$eeAlgo.pub \
     -pub $TMPDIR/ee.$eeAlgo.pub"
-test_expect_success "$eeAlgo: EE chain" "keytool \
+test_expect_success "$eeAlgo: EE chain" "cmkeytool \
     -ca-pub $TMPDIR/ca.$caAlgo.pub \
     -ca-pub $TMPDIR/subca.$eeAlgo.pub \
     -pub $TMPDIR/ee.$eeAlgo.pub \
index 6cb90c9ba8f14172708406ed483315994a01517eb599ad7b4858374d15885ff4..0b18e9cb482941b4aab62a8baeea8dd9a907de031d0595f275f63eeea8793e31 100755 (executable)
@@ -1,6 +1,6 @@
 #!/bin/sh
 
-test_description="Check that KEM certificates generation works"
+test_description="Check KEM certificates generation"
 . $SHARNESS_TEST_SRCDIR/sharness.sh
 
 TMPDIR=${TMPDIR:-/tmp}
@@ -8,7 +8,7 @@ TMPDIR=${TMPDIR:-/tmp}
 echo "mceliece6960119-x25519
 sntrup4591761-x25519" | while read algo ; do
 
-test_expect_success "$algo: generation" "keytool \
+test_expect_success "$algo: generation" "cmkeytool \
     -algo $algo \
     -ku kem -subj CN=DH \
     -prv $TMPDIR/kem.$algo.prv -pub $TMPDIR/kem.$algo.pub"
index 3a1e12d4e4ecd3261dcb77e7a65f558e847e1125b579cf0e0f41370b955d1e37..14d61113c431179837d032d1c23d0ee7b83a424cc595ba64d8614f318ebaa61c 100755 (executable)
@@ -1,6 +1,6 @@
 #!/bin/sh
 
-test_description="Check that basic signing functionality works"
+test_description="Check signing"
 . $SHARNESS_TEST_SRCDIR/sharness.sh
 
 TMPDIR=${TMPDIR:-/tmp}
@@ -11,7 +11,7 @@ ed25519-blake2b" | while read keyalgo ; do
 
 subj="-subj what=ever"
 typ="some-different-type"
-test_expect_success "$keyalgo: pub generation" "keytool \
+test_expect_success "$keyalgo: pub generation" "cmkeytool \
     -algo $keyalgo -ku sig $subj \
     -prv $TMPDIR/sign.$keyalgo.prv -pub $TMPDIR/sign.$keyalgo.pub"
 dd if=/dev/urandom of=$TMPDIR/sign.$keyalgo.data bs=300K count=1 2>/dev/null
@@ -21,32 +21,32 @@ badEncTo="-encrypted-to $(uuidgen)"
 for merkle in "" "-merkle" ; do
 
 algo=${keyalgo}${merkle}
-test_expect_success "$algo: signing" "sigtool $merkle \
+test_expect_success "$algo: signing" "cmsigtool $merkle \
     -prv $TMPDIR/sign.$keyalgo.prv -pub $TMPDIR/sign.$keyalgo.pub -type $typ \
     $encTo <$TMPDIR/sign.$keyalgo.data >$TMPDIR/sign.$algo.sig"
-test_expect_success "$algo: verifying" "sigtool \
+test_expect_success "$algo: verifying" "cmsigtool \
     -verify -pub $TMPDIR/sign.$keyalgo.pub -type $typ \
         <$TMPDIR/sign.$algo.sig >$TMPDIR/sign.data.got"
 test_expect_success "$algo: comparing" \
     "test_cmp $TMPDIR/sign.$keyalgo.data $TMPDIR/sign.data.got"
-test_expect_success "$algo: differing type" "! sigtool \
+test_expect_success "$algo: differing type" "! cmsigtool \
     -verify -pub $TMPDIR/sign.$keyalgo.pub <$TMPDIR/sign.$algo.sig >/dev/null"
-test_expect_success "$algo: good encTo" "! sigtool \
+test_expect_success "$algo: good encTo" "! cmsigtool \
     -verify -pub $TMPDIR/sign.$keyalgo.pub $encTo <$TMPDIR/sign.$algo.sig >/dev/null"
-test_expect_success "$algo: bad encTo" "! sigtool \
+test_expect_success "$algo: bad encTo" "! cmsigtool \
     -verify -pub $TMPDIR/sign.$keyalgo.pub $badEncTo <$TMPDIR/sign.$algo.sig >/dev/null"
 
-test_expect_success "$algo: detached signing" "sigtool -detached $merkle \
+test_expect_success "$algo: detached signing" "cmsigtool -detached $merkle \
     -prv $TMPDIR/sign.$keyalgo.prv -pub $TMPDIR/sign.$keyalgo.pub -type $typ \
         <$TMPDIR/sign.$keyalgo.data >$TMPDIR/sign.$algo.detached.sig"
 test_expect_success "$algo: detached verifying" \
     "cat $TMPDIR/sign.$algo.detached.sig $TMPDIR/sign.$keyalgo.data |
-        sigtool -detached -verify -pub $TMPDIR/sign.$keyalgo.pub -type $typ"
-test_expect_success "$algo: differing type" "! sigtool -detached \
+        cmsigtool -detached -verify -pub $TMPDIR/sign.$keyalgo.pub -type $typ"
+test_expect_success "$algo: differing type" "! cmsigtool -detached \
     -verify -pub $TMPDIR/sign.$keyalgo.pub <$TMPDIR/sign.$algo.detached.sig >/dev/null"
-test_expect_success "$algo: good encTo" "! sigtool -detached \
+test_expect_success "$algo: good encTo" "! cmsigtool -detached \
     -verify -pub $TMPDIR/sign.$keyalgo.pub $encTo <$TMPDIR/sign.$algo.detached.sig >/dev/null"
-test_expect_success "$algo: bad encTo" "! sigtool -detached \
+test_expect_success "$algo: bad encTo" "! cmsigtool -detached \
     -verify -pub $TMPDIR/sign.$keyalgo.pub $badEncTo <$TMPDIR/sign.$algo.detached.sig >/dev/null"
 
 done
diff --git a/go/cm/enc/balloon.go b/go/cm/enc/balloon.go
deleted file mode 100644 (file)
index 87cc069..0000000
+++ /dev/null
@@ -1,12 +0,0 @@
-package encrypted
-
-const (
-       BalloonSaltLen  = 8
-       BalloonHKDFInfo = "keks/cm/encrypted/balloon-blake2b-hkdf"
-)
-
-type BalloonCost struct {
-       S uint64 `keks:"s"`
-       T uint64 `keks:"t"`
-       P uint64 `keks:"p"`
-}
diff --git a/go/cm/enc/balloon/cost/cost.go b/go/cm/enc/balloon/cost/cost.go
new file mode 100644 (file)
index 0000000..b723b60
--- /dev/null
@@ -0,0 +1,7 @@
+package cost
+
+type Cost struct {
+       S uint64 `keks:"s"`
+       T uint64 `keks:"t"`
+       P uint64 `keks:"p"`
+}
diff --git a/go/cm/enc/balloon/decap.go b/go/cm/enc/balloon/decap.go
new file mode 100644 (file)
index 0000000..32a16da
--- /dev/null
@@ -0,0 +1,71 @@
+// GoKEKS/CM -- KEKS-encoded cryptographic messages
+// Copyright (C) 2024-2025 Sergey Matveev <stargrave@stargrave.org>
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Lesser General Public License as
+// published by the Free Software Foundation, version 3 of the License.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+// GNU Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+package balloon
+
+import (
+       "bytes"
+       "crypto/hkdf"
+       "errors"
+       "hash"
+
+       "go.cypherpunks.su/balloon/v3"
+       cmenc "go.cypherpunks.su/keks/cm/enc"
+       chaPoly "go.cypherpunks.su/keks/cm/enc/chapoly"
+       "golang.org/x/crypto/blake2b"
+)
+
+const (
+       BalloonBLAKE2bHKDF = "balloon-blake2b-hkdf"
+       SaltLen            = 8
+       HKDFInfo           = "keks/cm/encrypted/balloon-blake2b-hkdf"
+)
+
+func blake2bHash() hash.Hash {
+       h, err := blake2b.New512(nil)
+       if err != nil {
+               panic(err)
+       }
+       return h
+}
+
+func Decapsulate(kem cmenc.KEM, encSalt, passphrase []byte) (cek []byte, err error) {
+       if kem.Salt == nil {
+               return nil, errors.New("missing salt")
+       }
+       if kem.BalloonCost == nil {
+               return nil, errors.New("missing cost")
+       }
+       var kek []byte
+       kek, err = hkdf.Expand(
+               blake2bHash,
+               balloon.H(
+                       blake2bHash,
+                       passphrase,
+                       append(encSalt, *kem.Salt...),
+                       int(kem.BalloonCost.S),
+                       int(kem.BalloonCost.T),
+                       int(kem.BalloonCost.P),
+               ),
+               HKDFInfo,
+               chaPoly.KeyLen,
+       )
+       if err != nil {
+               return nil, err
+       }
+       var buf bytes.Buffer
+       _, err = chaPoly.Open(&buf, bytes.NewReader(kem.CEK), kek, 1)
+       return buf.Bytes(), err
+}
index 021a2b697004109f9e4959840848cf38d9175d46f44e266ccbf9546391513526..d9d2700baa67ff67c078ff354ca79883410150aa61cbef7a63db2dd6fc0b5bfc 100644 (file)
@@ -50,7 +50,7 @@ type job struct {
 
 func do(
        w io.Writer,
-       seal bool,
+       blob, seal bool,
        r io.Reader,
        key []byte,
        procs int,
@@ -76,9 +76,13 @@ func do(
        blobChunkLen := PadLen + ChunkLen + overhead
        var blobDecoder *keks.BlobDecoder
        if seal {
-               total, err = keks.BlobAtomEncode(w, int64(blobChunkLen))
+               if blob {
+                       total, err = keks.BlobAtomEncode(w, int64(blobChunkLen))
+               }
        } else {
-               blobDecoder, err = keks.NewBlobDecoder(r, int64(blobChunkLen))
+               if blob {
+                       blobDecoder, err = keks.NewBlobDecoder(r, int64(blobChunkLen))
+               }
        }
        if err != nil {
                return
@@ -126,7 +130,11 @@ func do(
                for j := range dones {
                        <-j.processed
                        if seal {
-                               n, errW = keks.BinEncode(w, j.buf)
+                               if blob {
+                                       n, errW = keks.BinEncode(w, j.buf)
+                               } else {
+                                       n, errW = io.Copy(w, bytes.NewReader(j.buf))
+                               }
                        } else {
                                if len(j.buf) == 0 {
                                        n = 0
@@ -135,7 +143,7 @@ func do(
                                }
                        }
                        total += n
-                       if errW != nil {
+                       if errW != nil || n == 0 {
                                break
                        }
                        j.buf = j.buf[:blobChunkLen]
@@ -159,10 +167,15 @@ func do(
                if seal {
                        n, errR = io.ReadFull(r, j.buf[PadLen:PadLen+ChunkLen])
                } else {
-                       blobDecoder.SetReadBuf(j.buf)
-                       chunk, errR = blobDecoder.Next()
-                       n = len(chunk)
-                       j.buf = j.buf[:n]
+                       if blobDecoder == nil {
+                               n, errR = io.ReadFull(r, j.buf)
+                               j.buf = j.buf[:n]
+                       } else {
+                               blobDecoder.SetReadBuf(j.buf)
+                               chunk, errR = blobDecoder.Next()
+                               n = len(chunk)
+                               j.buf = j.buf[:n]
+                       }
                }
                total += int64(n)
                if errR != nil {
@@ -202,9 +215,17 @@ func do(
 }
 
 func Seal(w io.Writer, r io.Reader, key []byte, procs int) (total int64, err error) {
-       return do(w, true, r, key, procs)
+       return do(w, false, true, r, key, procs)
 }
 
 func Open(w io.Writer, r io.Reader, key []byte, procs int) (total int64, err error) {
-       return do(w, false, r, key, procs)
+       return do(w, false, false, r, key, procs)
+}
+
+func SealBlob(w io.Writer, r io.Reader, key []byte, procs int) (total int64, err error) {
+       return do(w, true, true, r, key, procs)
+}
+
+func OpenBlob(w io.Writer, r io.Reader, key []byte, procs int) (total int64, err error) {
+       return do(w, true, false, r, key, procs)
 }
index 016566667de09036a7b5391efdddba8b74fc9c504b63c9dfcff994f56828541f..0f289b2caf614422ac558b57d6600bd872800c2743639364d6f854a82c9c6967 100644 (file)
@@ -1,6 +1,7 @@
 package encrypted
 
-const (
-       BalloonBLAKE2bHKDF = "balloon-blake2b-hkdf"
-       ChaCha20Poly1305   = "chacha20poly1305"
-)
+const ChaCha20Poly1305 = "chacha20poly1305"
+
+type DEM struct {
+       A string `keks:"a"`
+}
diff --git a/go/cm/enc/enc.go b/go/cm/enc/enc.go
new file mode 100644 (file)
index 0000000..2a84f5c
--- /dev/null
@@ -0,0 +1,11 @@
+package encrypted
+
+import "github.com/google/uuid"
+
+type Encrypted struct {
+       DEM  DEM       `keks:"dem"`
+       KEM  []KEM     `keks:"kem"`
+       Salt uuid.UUID `keks:"salt"`
+
+       Payload []byte `keks:"payload,omitempty"`
+}
index 497f4f6e9035e8cfa506ff08e636a972795b4e556879d328dd6d75c5dc39a42d..94a7a95cb18dded434f8a19128ef3715bf6f6b8a076077ee80d2c776f59fbbb0 100644 (file)
@@ -2,7 +2,8 @@ package encrypted
 
 import (
        "github.com/google/uuid"
-       "go.cypherpunks.su/keks"
+
+       balloon "go.cypherpunks.su/keks/cm/enc/balloon/cost"
 )
 
 const (
@@ -16,20 +17,8 @@ type KEM struct {
        To  *uuid.UUID `keks:"to,omitempty"`
 
        // balloon-blake2b-hkdf related
-       Cost *BalloonCost `keks:"cost,omitempty"`
-       Salt *[]byte      `keks:"salt,omitempty"`
+       BalloonCost *balloon.Cost `keks:"cost,omitempty"`
+       Salt        *[]byte       `keks:"salt,omitempty"`
 
        Encap *[]byte `keks:"encap,omitempty"`
 }
-
-type DEM struct {
-       A string `keks:"a"`
-}
-
-type Encrypted struct {
-       DEM  DEM       `keks:"dem"`
-       KEM  []KEM     `keks:"kem"`
-       Salt uuid.UUID `keks:"salt"`
-
-       Ciphertext *keks.BlobChunked `keks:"ciphertext,omitempty"`
-}
index c5fe918dc806614c58000aa52f9f248649ecaa1f350fe29b66ae542c44477a67..0fc60d35bfe8f14b8f77c13ab80dd5e84fc8e94382ec3d88bb0af67bfe0c073b 100644 (file)
@@ -1,6 +1,6 @@
 module go.cypherpunks.su/keks/cm
 
-go 1.24
+go 1.24.0
 
 require (
        github.com/companyzero/sntrup4591761 v0.0.0-20220309191932-9e0f3af2f07a
diff --git a/go/cm/hash/hash.go b/go/cm/hash/hash.go
new file mode 100644 (file)
index 0000000..2491f4b
--- /dev/null
@@ -0,0 +1,7 @@
+package hash
+
+type Hashed struct {
+       Algo []string `keks:"a"`
+       Typ  string   `keks:"t"`
+       Hash [][]byte `keks:"hash"`
+}
diff --git a/go/cm/utils/mk-bin b/go/cm/utils/mk-bin
new file mode 100755 (executable)
index 0000000..c90d0aa
--- /dev/null
@@ -0,0 +1,9 @@
+#!/bin/sh -e
+
+GO_LDFLAGS="${GO_LDFLAGS:--s}"
+
+mkdir -p bin
+for cmd in enc hsh key sig ; do
+    cmd=${cmd}tool
+    go build -o bin/cm$cmd -ldflags "$GO_LDFLAGS" ./cmd/$cmd
+done
diff --git a/go/cmd/pp/go.mod b/go/cmd/pp/go.mod
new file mode 100644 (file)
index 0000000..b07a10e
--- /dev/null
@@ -0,0 +1,17 @@
+module go.cypherpunks.su/keks/cmd/pp
+
+go 1.24.0
+
+replace go.cypherpunks.su/keks => ../../
+
+require (
+       go.cypherpunks.su/keks v0.0.0-00010101000000-000000000000
+       go.cypherpunks.su/tai64n/v4 v4.1.0
+       golang.org/x/term v0.28.0
+)
+
+require (
+       github.com/google/uuid v1.6.0 // indirect
+       github.com/mitchellh/mapstructure v1.5.0 // indirect
+       golang.org/x/sys v0.29.0 // indirect
+)
diff --git a/go/cmd/pp/go.sum b/go/cmd/pp/go.sum
new file mode 100644 (file)
index 0000000..268b767
--- /dev/null
@@ -0,0 +1,10 @@
+github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
+github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
+github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY=
+github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
+go.cypherpunks.su/tai64n/v4 v4.1.0 h1:jW0EyklKXpSy9DSFMcDbu7XuLlMkn6kkpNWiMG6UT5c=
+go.cypherpunks.su/tai64n/v4 v4.1.0/go.mod h1:/uKUdhLOy8UciRKpapPaFXSOoa/SiXjs3XsDDpAz7OA=
+golang.org/x/sys v0.29.0 h1:TPYlXGxvx1MGTn2GiZDhnjPA9wZzZeGKHHmKhHYvgaU=
+golang.org/x/sys v0.29.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
+golang.org/x/term v0.28.0 h1:/Ts8HFuMR2E6IP/jlo7QVLZHggjKQbhu/7H0LJFr3Gg=
+golang.org/x/term v0.28.0/go.mod h1:Sw/lC2IAUZ92udQNf3WodGtn4k/XoLyZoh8v/8uiwek=
index 532781b1699c74c58156383f98004ddbd19baa7b439ab44cbde9ea008bfacf77..5d0d2b63f7994153b076cab2c2fc243e71f69a8c4a11dfb2d0665200b9664a4c 100644 (file)
@@ -33,7 +33,8 @@ import (
 )
 
 var (
-       MaxStrLen      = flag.Uint("max-str-len", 40, "Maximal string length to print")
+       MaxStrLen      = flag.Uint("max-str-len", 64,
+               "Maximal string length to print")
        MaxParseCycles = flag.Uint64("max-parse-cycles", 1<<63,
                "Maximal number of parse cycles to perform")
 )
index 8240e2d8f0ed32e0c3cbc5dd2d5c4ad2f8484be9c2e408bc67995c2be8da133e..4533458fa4398d63ee3676cf79555c8d2a928e05c89c77df98c5b32f74219019 100644 (file)
--- a/go/go.mod
+++ b/go/go.mod
@@ -1,12 +1,9 @@
 module go.cypherpunks.su/keks
 
-go 1.24
+go 1.24.0
 
 require (
        github.com/google/uuid v1.6.0
        github.com/mitchellh/mapstructure v1.5.0
        go.cypherpunks.su/tai64n/v4 v4.1.0
-       golang.org/x/term v0.28.0
 )
-
-require golang.org/x/sys v0.29.0 // indirect
index 268b767f0a6c374b4de4e0d48088443409edb37abf34ba22cdfcb288cab20234..063c682ef8bc10d607af9505018ff485e66d94e8febb95a5a280ac024547ac33 100644 (file)
--- a/go/go.sum
+++ b/go/go.sum
@@ -4,7 +4,3 @@ github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyua
 github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
 go.cypherpunks.su/tai64n/v4 v4.1.0 h1:jW0EyklKXpSy9DSFMcDbu7XuLlMkn6kkpNWiMG6UT5c=
 go.cypherpunks.su/tai64n/v4 v4.1.0/go.mod h1:/uKUdhLOy8UciRKpapPaFXSOoa/SiXjs3XsDDpAz7OA=
-golang.org/x/sys v0.29.0 h1:TPYlXGxvx1MGTn2GiZDhnjPA9wZzZeGKHHmKhHYvgaU=
-golang.org/x/sys v0.29.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
-golang.org/x/term v0.28.0 h1:/Ts8HFuMR2E6IP/jlo7QVLZHggjKQbhu/7H0LJFr3Gg=
-golang.org/x/term v0.28.0/go.mod h1:Sw/lC2IAUZ92udQNf3WodGtn4k/XoLyZoh8v/8uiwek=
diff --git a/go/utils/mk-bin b/go/utils/mk-bin
new file mode 100755 (executable)
index 0000000..133b75f
--- /dev/null
@@ -0,0 +1,8 @@
+#!/bin/sh -e
+
+GO_LDFLAGS="${GO_LDFLAGS:--s}"
+
+mkdir -p bin
+bin=$(realpath bin)
+cd cmd/pp
+go build -o $bin/kekspp -ldflags "$GO_LDFLAGS"
index 45300cea32ad525460edfa9a8189418fa4432e303071b5be0061abf8365fa3f1..67e5a93141af7b13e984b15c2757b63197e1c612d5c55f04780725de7585713c 100644 (file)
@@ -4,7 +4,7 @@ cm-encrypted = {
     dem: dem,
     kem: [+ kem],
     salt: uuid,
-    ? ciphertext: blob,
+    ? payload: bytes,
 }
 
 dem = dem-chacha20poly1305 / dem-kuznechik-ctracpkm-hmac
index c74e0415ae5d2aca356592642c2300018764152d622bfcd91cb0caa6b8959397..912d51ab447656906cf4935e3a3685c5fa8267fbb1f8d8ad641972bdf0f18642 100644 (file)
@@ -7,15 +7,16 @@ Stored in a file, it should begin with "cm/encrypted" @ref{MAGIC, magic}.
 
 @verbatiminclude cm/encrypted.cddl
 
-@code{/ciphertext} contains the ciphertext. It is encrypted with random
+@code{/payload} contains the ciphertext. It is encrypted with random
 "content encryption key" (CEK) with an algorithm specified in
 @code{/dem/a} (data encapsulation mechanism). @code{/dem} may contain
 additional fields supplementing the decryption process, like
 initialisation vector.
 
-@code{/ciphertext} is a BLOB, which chunk's length depends on DEM
-algorithm. If it is absent, then ciphertext is provided by other means,
-for example just following the @code{cm-encrypted} structure.
+If @code{/payload} is absent, then ciphertext is provided by other
+means, for example just by following the @code{cm-encrypted} structure.
+It is recommended to encode it as a BLOB, which chunk's length depends
+on DEM algorithm.
 
 CEK is encapsulated in @code{/kem/*} entries (key encapsulation
 mechanism), using @code{/kem/*/a} algorithm. @code{/kem/*/cek} field
@@ -54,7 +55,7 @@ ChaCha20-Poly1305(key=KEY, ad="",
     payload. It equals to 0x01 for the last chunk and to 0x00 for other ones.
     Last chunk should be smaller than previous ones, maybe (payload) even empty.
 
-    @code{/ciphertext}'s chunk length equals to 32+128KiB+16 bytes.
+    @code{/payload}'s chunk length equals to 32+128KiB+16 bytes.
 
 @node cm-encrypted-kuznechik-ctracpkm-hmac
 @cindex cm-encrypted-kuznechik-ctracpkm-hmac
@@ -73,7 +74,7 @@ Kenc || IV || Kauth = CEK
     size and IV initialisation vector. Authentication of ciphertext is
     performed with Streebog-512 (ГОСТ Р 34.11-2012) in HMAC mode.
 
-    @code{/ciphertext}'s chunk length equals to 128KiB bytes.
+    @code{/payload}'s chunk length equals to 128KiB bytes.
 
 @node cm-encrypted-balloon-blake2b-hkdf
 @cindex cm-encrypted-balloon-blake2b-hkdf
index 81955906c4390d21d999d7d541d2343515a951dcd10d4bd375fb8e1c527c9d7a..ac3a22082cda8e408c561d7e3ace2bdc8f6efafcd5fc44ea8071254e3b0ae0b4 100644 (file)
@@ -3,6 +3,6 @@ ai = text ; algorithm identifier
 cm-hashed = {
     a: [+ ai],
     t: text, ; type of the content
-    v: bytes / text / blob / map / list, ; content itself
+    ? v: bytes / blob, ; content itself
     hash: [+ bytes], ; hash values
 }
index e0112d723281be4c32a3aeca174e7ec4bced04b80127576f907105e932f78571..fd5e93f3923ed9566f2debdcb7573ca035ef67370dfb356fbc4ddcf46fd37289 100644 (file)
@@ -14,11 +14,6 @@ Stored in a file, it should begin with "cm/hashed" @ref{MAGIC, magic}.
 
 @code{/t} tells the type of the data inside.
 
-If @code{/v} is either a MAP or LIST, then its encoded binary
-representation is hashed. If it is BIN/STR or BLOB, then its binary
-contents are hashed. So hash will stay the same even if data is
-converted from BIN to BLOB.
-
 @code{/hash} contains the hash values for all corresponding @code{/a}
 algorithms.