--- /dev/null
+// 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 cm
+
+import (
+ "go.cypherpunks.su/keks"
+ ed25519blake2b "go.cypherpunks.su/keks/cm/ed25519-blake2b"
+ "go.cypherpunks.su/keks/cm/gost"
+ mceliece6960119x25519 "go.cypherpunks.su/keks/cm/mceliece6960119-x25519"
+ sntrup4591761x25519 "go.cypherpunks.su/keks/cm/sntrup4591761-x25519"
+)
+
+const (
+ BalloonBLAKE2bHKDF = "balloon-blake2b-hkdf"
+ ChaCha20Poly1305 = "chacha20poly1305"
+ ClassicMcEliece6960119X25519 = mceliece6960119x25519.ClassicMcEliece6960119X25519
+ ClassicMcEliece6960119X25519HKDFSHAKE256 = mceliece6960119x25519.ClassicMcEliece6960119X25519HKDFSHAKE256
+ Ed25519BLAKE2b = ed25519blake2b.Ed25519BLAKE2b
+ Ed25519PhBLAKE2b = ed25519blake2b.Ed25519PhBLAKE2b
+ Ed25519PhBLAKE2bMerkle = ed25519blake2b.Ed25519PhBLAKE2bMerkle
+ GOST3410256A = gost.GOST3410256A
+ GOST3410256AMerkle = gost.GOST3410256AMerkle
+ GOST3410512C = gost.GOST3410512C
+ GOST3410512CMerkle = gost.GOST3410512CMerkle
+ SNTRUP4591761X25519 = sntrup4591761x25519.SNTRUP4591761X25519
+ SNTRUP4591761X25519HKDFBLAKE2b = sntrup4591761x25519.SNTRUP4591761X25519HKDFBLAKE2b
+
+ EncryptedMagic = keks.Magic("cm/encrypted")
+ HashedMagic = keks.Magic("cm/hashed")
+ PrvMagic = keks.Magic("cm/prv")
+)
-// GoKEKS/PKI -- PKI-related capabilities based on KEKS encoded formats
+// 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
// 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 pki
+package cm
import (
"bytes"
"github.com/google/uuid"
"go.cypherpunks.su/keks"
- pkihash "go.cypherpunks.su/keks/pki/hash"
+ cmhash "go.cypherpunks.su/keks/cm/hash"
)
// Algorithm-value often used structure.
var hasher hash.Hash
switch av.A {
case Ed25519BLAKE2b, SNTRUP4591761X25519:
- hasher = pkihash.ByName(pkihash.BLAKE2b256)
+ hasher = cmhash.ByName(cmhash.BLAKE2b256)
case GOST3410256A, GOST3410512C:
- hasher = pkihash.ByName(pkihash.Streebog256)
+ hasher = cmhash.ByName(cmhash.Streebog256)
case ClassicMcEliece6960119X25519:
- hasher = pkihash.ByName(pkihash.SHAKE128)
+ hasher = cmhash.ByName(cmhash.SHAKE128)
default:
id = uuid.Nil
return
-// enctool -- dealing with KEKS-encoded pki-encrypted utility
+// enctool -- dealing with KEKS-encoded cm-encrypted utility
// Copyright (C) 2024-2025 Sergey Matveev <stargrave@stargrave.org>
//
// This program is free software: you can redistribute it and/or modify
-// enctool -- dealing with KEKS-encoded pki-encrypted utility
+// enctool -- dealing with KEKS-encoded cm-encrypted utility
// Copyright (C) 2024-2025 Sergey Matveev <stargrave@stargrave.org>
//
// This program is free software: you can redistribute it and/or modify
"golang.org/x/term"
"go.cypherpunks.su/keks"
- "go.cypherpunks.su/keks/pki"
- pkihash "go.cypherpunks.su/keks/pki/hash"
- "go.cypherpunks.su/keks/pki/utils"
+ "go.cypherpunks.su/keks/cm"
+ cmhash "go.cypherpunks.su/keks/cm/hash"
+ "go.cypherpunks.su/keks/cm/utils"
"go.cypherpunks.su/keks/types"
)
const (
BalloonSaltLen = 8
- BalloonHKDFSalt = "keks/pki/encrypted/balloon-blake2b-hkdf"
- SNTRUP4591761X25519Salt = "keks/pki/encrypted/sntrup4591761-x25519-hkdf-blake2b"
- ClassicMcEliece6960119X25519Salt = "keks/pki/encrypted/mceliece6960119-x25519-hkdf-shake256"
+ BalloonHKDFSalt = "keks/cm/encrypted/balloon-blake2b-hkdf"
+ SNTRUP4591761X25519Salt = "keks/cm/encrypted/sntrup4591761-x25519-hkdf-blake2b"
+ ClassicMcEliece6960119X25519Salt = "keks/cm/encrypted/mceliece6960119-x25519-hkdf-shake256"
BindFdNum = 3 + 1
)
balloonT := flag.Int("balloon-t", 3, "Balloon's time cost")
balloonP := flag.Int("balloon-p", 2, "Balloon's number of threads")
doDecrypt := flag.Bool("d", false, "Decrypt")
- var pubs []*pki.Pub
- flag.Func("cer", "Path to certificate to encrypt to", func(v string) error {
- signed, err := pki.CerParse(utils.MustReadFile(v))
+ var pubs []*cm.Pub
+ flag.Func("pub", "Path to public key to encrypt to", func(v string) error {
+ signed, err := cm.PubParse(utils.MustReadFile(v))
if err != nil {
return err
}
- load := signed.CerLoad()
+ load := signed.PubLoad()
if load.KU == nil {
log.Println(v, "does not have key usages")
} else {
- if _, ok := (*load.KU)[pki.KUKEM]; !ok {
- log.Println(v, "does not have", pki.KUKEM, "key usage")
+ if _, ok := (*load.KU)[cm.KUKEM]; !ok {
+ log.Println(v, "does not have", cm.KUKEM, "key usage")
}
}
if len(load.Pub) != 1 {
pubs = append(pubs, &load.Pub[0])
return err
})
- var prvs []*pki.AV
+ var prvs []*cm.AV
flag.Func("prv", "Our private keys for decryption", func(v string) (err error) {
magic, data := keks.StripMagic(utils.MustReadFile(v))
- if magic == "" || magic != pki.PrvKeyMagic {
+ if magic == "" || magic != cm.PrvMagic {
return errors.New("wrong magic")
}
- var av pki.AV
+ var av cm.AV
d := keks.NewDecoderFromBytes(data, &keks.DecodeOpts{MaxStrLen: 1 << 16})
if err = d.DecodeStruct(&av); err != nil {
return err
if t != types.Magic {
log.Fatal("no magic met")
}
- if d.Iter().Magic() != pki.EncryptedMagic {
+ if d.Iter().Magic() != cm.EncryptedMagic {
log.Fatal("wrong magic")
}
}
bindFd.WriteString(encrypted.Bind.String() + "\n")
bindFd.Close()
}
- if encrypted.DEM.A != pki.ChaCha20Poly1305 {
+ if encrypted.DEM.A != cm.ChaCha20Poly1305 {
log.Fatalln("unsupported DEM:", encrypted.DEM.A)
}
if len(encrypted.KEM) == 0 {
}
for kemIdx, kem := range encrypted.KEM {
switch kem.A {
- case pki.BalloonBLAKE2bHKDF:
+ case cm.BalloonBLAKE2bHKDF:
if !*passphrase {
log.Println(kemIdx, kem.A, "skipping because no -passwd")
continue
}
cek = cekp
}
- case pki.SNTRUP4591761X25519HKDFBLAKE2b:
+ case cm.SNTRUP4591761X25519HKDFBLAKE2b:
if len(prvs) == 0 {
log.Println(kemIdx, kem.A, "skipping because no -prv")
continue
cek = cekp
}
}
- case pki.ClassicMcEliece6960119X25519HKDFSHAKE256:
+ case cm.ClassicMcEliece6960119X25519HKDFSHAKE256:
if len(prvs) == 0 {
log.Println(kemIdx, kem.A, "skipping because no -prv")
continue
keyMcEliece, keyX25519,
}, []byte{})
var kek []byte
- kek, err = hkdf.Extract(pkihash.NewSHAKE256,
+ kek, err = hkdf.Extract(cmhash.NewSHAKE256,
ikm, []byte(ClassicMcEliece6960119X25519Salt))
if err != nil {
log.Fatal(err)
log.Fatal(err)
}
kem := KEM{
- A: pki.BalloonBLAKE2bHKDF,
+ A: cm.BalloonBLAKE2bHKDF,
Salt: &salt,
Cost: &BalloonCost{
S: uint64(*balloonS),
}
for _, pub := range pubs {
switch pub.A {
- case pki.SNTRUP4591761X25519:
+ case cm.SNTRUP4591761X25519:
if len(pub.V) != sntrup4591761.PublicKeySize+32 {
log.Fatalln("invalid public keys len")
}
if err != nil {
log.Fatal(err)
}
- kem := KEM{A: pki.SNTRUP4591761X25519HKDFBLAKE2b}
+ kem := KEM{A: cm.SNTRUP4591761X25519HKDFBLAKE2b}
encap := append(ciphertext[:], ourPubX25519.Bytes()...)
kem.Encap = &encap
{
kem.To = &pub.Id
}
kems = append(kems, kem)
- case pki.ClassicMcEliece6960119X25519:
+ case cm.ClassicMcEliece6960119X25519:
scheme := mceliece6960119.Scheme()
if len(pub.V) != scheme.PublicKeySize()+32 {
log.Fatalln("invalid public keys len")
if err != nil {
log.Fatal(err)
}
- kem := KEM{A: pki.ClassicMcEliece6960119X25519HKDFSHAKE256}
+ kem := KEM{A: cm.ClassicMcEliece6960119X25519HKDFSHAKE256}
encap := append(ciphertext[:], ourPubX25519.Bytes()...)
kem.Encap = &encap
{
keyMcEliece[:], keyX25519,
}, []byte{})
var kek []byte
- kek, err = hkdf.Extract(pkihash.NewSHAKE256,
+ kek, err = hkdf.Extract(cmhash.NewSHAKE256,
ikm, []byte(ClassicMcEliece6960119X25519Salt))
if err != nil {
log.Fatal(err)
}
{
var hdr bytes.Buffer
- if _, err = keks.Encode(&hdr, pki.EncryptedMagic, nil); err != nil {
+ if _, err = keks.Encode(&hdr, cm.EncryptedMagic, nil); err != nil {
log.Fatal(err)
}
if _, err = keks.Encode(&hdr, &Encrypted{
Bind: binding,
KEM: kems,
- DEM: DEM{A: pki.ChaCha20Poly1305},
+ DEM: DEM{A: cm.ChaCha20Poly1305},
}, nil); err != nil {
log.Fatal(err)
}
-// enctool -- dealing with KEKS-encoded pki-encrypted utility
+// enctool -- dealing with KEKS-encoded cm-encrypted utility
// Copyright (C) 2024-2025 Sergey Matveev <stargrave@stargrave.org>
//
// This program is free software: you can redistribute it and/or modify
func usage() {
fmt.Fprintf(os.Stderr, `Usage:
- Encrypt to recipient:
- enctool -cer CER [-include-to] [-bind UUID] <DATA >DATA.encrypted [4>bind.value]
+ Encrypt to recipient(s):
+ enctool -pub PUB [-pub ...] [-include-to] [-bind UUID]
+ <DATA >DATA.encrypted [4>bind.value]
Encrypt on passphrase:
- enctool -p [-bind UUID] <DATA >DATA.encrypted [4>bind.value]
- [-balloon-s X] [-balloon-t X] [-balloon-p X]
+ enctool -p [-bind UUID] [-balloon-s X] [-balloon-t X] [-balloon-p X]
+ <DATA >DATA.encrypted [4>bind.value]
Decrypt by providing possible KEMs:
enctool -d [-p] [-prv PRV ...] <DATA.encrypted >DATA [4>bind.value]
"go.cypherpunks.su/gogost/v6/gost34112012256"
"go.cypherpunks.su/gogost/v6/gost34112012512"
- ed25519blake2b "go.cypherpunks.su/keks/pki/ed25519-blake2b"
- "go.cypherpunks.su/keks/pki/gost"
- pkihash "go.cypherpunks.su/keks/pki/hash"
- "go.cypherpunks.su/keks/pki/hash/merkle"
+ ed25519blake2b "go.cypherpunks.su/keks/cm/ed25519-blake2b"
+ "go.cypherpunks.su/keks/cm/gost"
+ cmhash "go.cypherpunks.su/keks/cm/hash"
+ "go.cypherpunks.su/keks/cm/hash/merkle"
)
func main() {
workers := flag.Int("p", runtime.NumCPU(), "Parallel workers")
chunkLenK := flag.Int("c", merkle.DefaultChunkLen/1024, "Chunk size, KiB")
- algo := flag.String("a", pkihash.BLAKE2b, "Algorithm to use")
+ algo := flag.String("a", cmhash.BLAKE2b, "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()
if *list {
- fmt.Println(pkihash.BLAKE2bMerkle)
- fmt.Println(pkihash.SHA2512 + "-merkle")
- fmt.Println(pkihash.SHAKE128Merkle)
- fmt.Println(pkihash.SHAKE256Merkle)
- fmt.Println(pkihash.Streebog256Merkle)
- fmt.Println(pkihash.Streebog512Merkle)
+ fmt.Println(cmhash.BLAKE2bMerkle)
+ fmt.Println(cmhash.SHA2512 + "-merkle")
+ fmt.Println(cmhash.SHAKE128Merkle)
+ fmt.Println(cmhash.SHAKE256Merkle)
+ fmt.Println(cmhash.Streebog256Merkle)
+ fmt.Println(cmhash.Streebog512Merkle)
return
}
chunkLen := 1024 * *chunkLenK
var hasher *merkle.Hasher
switch *algo {
- case pkihash.BLAKE2bMerkle:
+ case cmhash.BLAKE2bMerkle:
hasher = ed25519blake2b.NewMerkleHasher(chunkLen, *workers).(*merkle.Hasher)
- case pkihash.SHA2512 + "-merkle":
+ case cmhash.SHA2512 + "-merkle":
hasher = merkle.NewHasherPrefixed(sha512.New, chunkLen, *workers)
- case pkihash.SHAKE128Merkle:
- hasher = pkihash.NewSHAKE128MerkleHasher(chunkLen, *workers).(*merkle.Hasher)
- case pkihash.SHAKE256Merkle:
- hasher = pkihash.NewSHAKE256MerkleHasher(chunkLen, *workers).(*merkle.Hasher)
- case pkihash.Streebog256Merkle:
+ case cmhash.SHAKE128Merkle:
+ hasher = cmhash.NewSHAKE128MerkleHasher(chunkLen, *workers).(*merkle.Hasher)
+ case cmhash.SHAKE256Merkle:
+ hasher = cmhash.NewSHAKE256MerkleHasher(chunkLen, *workers).(*merkle.Hasher)
+ case cmhash.Streebog256Merkle:
hasher = gost.NewMerkleHasher(gost34112012256.New, chunkLen, *workers).(*merkle.Hasher)
- case pkihash.Streebog512Merkle:
+ case cmhash.Streebog512Merkle:
hasher = gost.NewMerkleHasher(gost34112012512.New, chunkLen, *workers).(*merkle.Hasher)
default:
log.Fatal("unknown -a")
--- /dev/null
+#!/bin/sh
+
+test_description="Check that basic GOST-related functionality works"
+. $SHARNESS_TEST_SRCDIR/sharness.sh
+
+TMPDIR=${TMPDIR:-/tmp}
+
+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 \
+ -algo $caAlgo \
+ -ku sig $subj \
+ -prv $TMPDIR/ca.prv -pub $TMPDIR/ca.pub"
+test_expect_success "$caAlgo: CA generation" "keytool \
+ -pub $TMPDIR/ca.pub \
+ -ca-prv $TMPDIR/ca.prv -ca-pub $TMPDIR/ca.pub"
+test_expect_success "$caAlgo: CA regeneration" "keytool \
+ -pub $TMPDIR/ca.pub \
+ -ca-prv $TMPDIR/ca.prv -ca-pub $TMPDIR/ca.pub"
+test_expect_success "$caAlgo: CA self-signature" "keytool \
+ -ca-pub $TMPDIR/ca.pub \
+ -pub $TMPDIR/ca.pub \
+ -verify"
+
+subj="-subj CN=SubCA -subj C=RU"
+test_expect_success "$eeAlgo: SubCA load generation" "keytool \
+ -algo $eeAlgo \
+ -ku sig $subj \
+ -prv $TMPDIR/subca.prv -pub $TMPDIR/subca.pub"
+test_expect_success "$eeAlgo: SubCA generation" "keytool \
+ -pub $TMPDIR/subca.pub \
+ -ca-pub $TMPDIR/ca.pub -ca-prv $TMPDIR/ca.prv"
+test_expect_success "$eeAlgo: SubCA signature" "keytool \
+ -ca-pub $TMPDIR/ca.pub \
+ -pub $TMPDIR/subca.pub \
+ -verify"
+
+subj="-subj CN=EE -subj C=RU"
+test_expect_success "$eeAlgo: EE load generation" "keytool \
+ -algo $eeAlgo $subj \
+ -prv $TMPDIR/ee.prv -pub $TMPDIR/ee.pub"
+test_expect_success "$eeAlgo: EE generation" "keytool \
+ -ca-prv $TMPDIR/subca.prv -ca-pub $TMPDIR/subca.pub \
+ -pub $TMPDIR/ee.pub"
+test_expect_success "$eeAlgo: EE chain" "keytool \
+ -ca-pub $TMPDIR/ca.pub \
+ -ca-pub $TMPDIR/subca.pub \
+ -pub $TMPDIR/ee.pub \
+ -verify"
+
+done
+
+test_done
-// certool -- dealing with KEKS-encoded certificates utility
+// keytool -- dealing with KEKS-encoded keypairs utility
// Copyright (C) 2024-2025 Sergey Matveev <stargrave@stargrave.org>
//
// This program is free software: you can redistribute it and/or modify
"time"
"go.cypherpunks.su/keks"
- "go.cypherpunks.su/keks/pki"
- ed25519blake2b "go.cypherpunks.su/keks/pki/ed25519-blake2b"
- "go.cypherpunks.su/keks/pki/gost"
- mceliece6960119x25519 "go.cypherpunks.su/keks/pki/mceliece6960119-x25519"
- "go.cypherpunks.su/keks/pki/sign"
- sntrup4591761x25519 "go.cypherpunks.su/keks/pki/sntrup4591761-x25519"
- "go.cypherpunks.su/keks/pki/utils"
+ "go.cypherpunks.su/keks/cm"
+ ed25519blake2b "go.cypherpunks.su/keks/cm/ed25519-blake2b"
+ "go.cypherpunks.su/keks/cm/gost"
+ mceliece6960119x25519 "go.cypherpunks.su/keks/cm/mceliece6960119-x25519"
+ "go.cypherpunks.su/keks/cm/sign"
+ sntrup4591761x25519 "go.cypherpunks.su/keks/cm/sntrup4591761-x25519"
+ "go.cypherpunks.su/keks/cm/utils"
)
func main() {
return nil
},
)
- var issuingCers []string
+ var issuingPubs []string
flag.Func(
- "ca-cer",
- "Add CA certificate to the chain",
+ "ca-pub",
+ "Add certification public key to the chain",
func(v string) error {
- issuingCers = append(issuingCers, v)
+ issuingPubs = append(issuingPubs, v)
return nil
},
)
sinceRaw := flag.String("since", "",
"Optional notBefore, \"2006-01-02 15:04:05\" format")
lifetime := flag.Uint("lifetime", 365,
- "Lifetime of the certificate, days")
- algo := flag.String("algo", pki.Ed25519BLAKE2b, "Public key algorithm")
+ "Lifetime of the certification, days")
+ algo := flag.String("algo", cm.Ed25519BLAKE2b, "Public key algorithm")
issuingPrv := flag.String("ca-prv", "",
"Path to private key file for issuing with")
prvPath := flag.String("prv", "", "Path to private key file")
- cerPath := flag.String("cer", "", "Path to certificate file")
- verify := flag.Bool("verify", false, "Verify provided -cer with -ca-cer")
+ pubPath := flag.String("pub", "", "Path to public key file")
+ verify := flag.Bool("verify", false, "Verify provided -pub with -ca-pub")
doList := flag.Bool("list-algo", false, "List available algorithms")
flag.Parse()
if *doList {
algos := []string{
- pki.Ed25519BLAKE2b,
- pki.GOST3410256A,
- pki.GOST3410512C,
- pki.SNTRUP4591761X25519,
- pki.ClassicMcEliece6960119X25519,
+ cm.Ed25519BLAKE2b,
+ cm.GOST3410256A,
+ cm.GOST3410512C,
+ cm.SNTRUP4591761X25519,
+ cm.ClassicMcEliece6960119X25519,
}
sort.Strings(algos)
for _, s := range algos {
return
}
- if *cerPath == "" {
- log.Fatal("no -cer is set")
+ if *pubPath == "" {
+ log.Fatal("no -pub is set")
}
var err error
till := since.Add(time.Duration(*lifetime) * 24 * time.Hour)
var caPrv sign.Iface
- var caCers []*pki.Signed
- for _, issuingCer := range issuingCers {
- var signed *pki.Signed
- signed, err = pki.CerParse(utils.MustReadFile(issuingCer))
+ var caPubs []*cm.Signed
+ for _, issuingPub := range issuingPubs {
+ var signed *cm.Signed
+ signed, err = cm.PubParse(utils.MustReadFile(issuingPub))
if err != nil {
log.Fatal(err)
}
- caCers = append(caCers, signed)
+ caPubs = append(caPubs, signed)
}
- if len(caCers) > 0 && !*verify {
+ if len(caPubs) > 0 && !*verify {
if *issuingPrv == "" {
log.Fatal("no -ca-prv is set")
}
- caPrv, _, err = pki.PrvParse(utils.MustReadFile(*issuingPrv))
+ caPrv, _, err = cm.PrvParse(utils.MustReadFile(*issuingPrv))
if err != nil {
log.Fatal(err)
}
}
if *verify {
- var signed *pki.Signed
- signed, err = pki.CerParse(utils.MustReadFile(*cerPath))
+ var signed *cm.Signed
+ signed, err = cm.PubParse(utils.MustReadFile(*pubPath))
if err != nil {
log.Fatal(err)
}
- err = signed.CerVerify(caCers, time.Now().UTC())
+ err = signed.CertificationVerify(caPubs, time.Now().UTC())
if err != nil {
log.Fatal(err)
}
}
var prvRaw []byte
- var cerLoad *pki.CerLoad
- var signed *pki.Signed
+ var pubLoad *cm.PubLoad
+ var signed *cm.Signed
if caPrv != nil {
- signed, err = pki.CerParse(utils.MustReadFile(*cerPath))
+ signed, err = cm.PubParse(utils.MustReadFile(*pubPath))
if err != nil {
log.Fatal(err)
}
- cerLoad = signed.CerLoad()
+ pubLoad = signed.PubLoad()
} else {
if len(subj) == 0 {
log.Fatal("no -subj is set")
log.Fatal("no -prv is set")
}
switch *algo {
- case pki.Ed25519BLAKE2b:
+ case cm.Ed25519BLAKE2b:
_, prvRaw, pub, err = ed25519blake2b.NewKeypair()
- case pki.GOST3410256A, pki.GOST3410512C:
+ case cm.GOST3410256A, cm.GOST3410512C:
_, prvRaw, pub, err = gost.NewKeypair(*algo)
- case pki.SNTRUP4591761X25519:
+ case cm.SNTRUP4591761X25519:
prvRaw, pub, err = sntrup4591761x25519.NewKeypair()
- case pki.ClassicMcEliece6960119X25519:
+ case cm.ClassicMcEliece6960119X25519:
prvRaw, pub, err = mceliece6960119x25519.NewKeypair()
default:
err = errors.New("unknown -algo specified")
}
{
var buf bytes.Buffer
- if _, err = keks.Encode(&buf, pki.PrvKeyMagic, nil); err != nil {
+ if _, err = keks.Encode(&buf, cm.PrvMagic, nil); err != nil {
log.Fatal(err)
}
- if _, err = keks.Encode(&buf, pki.AV{A: *algo, V: prvRaw}, nil); err != nil {
+ if _, err = keks.Encode(&buf, cm.AV{A: *algo, V: prvRaw}, nil); err != nil {
log.Fatal(err)
}
err = os.WriteFile(*prvPath, buf.Bytes(), 0o600)
}
}
{
- pubMap := pki.Pub{A: *algo, V: pub}
+ pubMap := cm.Pub{A: *algo, V: pub}
{
- av := pki.AV{A: *algo, V: pub}
+ av := cm.AV{A: *algo, V: pub}
pubMap.Id = av.Id()
}
- cerLoad = &pki.CerLoad{Subj: subj, Pub: []pki.Pub{pubMap}}
+ pubLoad = &cm.PubLoad{Subj: subj, Pub: []cm.Pub{pubMap}}
}
if len(ku) > 0 {
- cerLoad.KU = &ku
+ pubLoad.KU = &ku
}
}
{
- cerLoadAny := any(cerLoad)
- signed = &pki.Signed{Load: pki.SignedLoad{T: "cer", V: &cerLoadAny}}
+ pubLoadAny := any(pubLoad)
+ signed = &cm.Signed{Load: cm.SignedLoad{T: "pub", V: &pubLoadAny}}
}
if caPrv != nil {
- if err = signed.CerIssueWith(
- caCers[0].CerLoad(), caPrv, since, till,
+ if err = signed.CertifyWith(
+ caPubs[0].PubLoad(), caPrv, since, till,
); err != nil {
log.Fatal(err)
}
{
var buf bytes.Buffer
- if _, err = keks.Encode(&buf, pki.CerMagic, nil); err != nil {
+ if _, err = keks.Encode(&buf, cm.PubMagic, nil); err != nil {
log.Fatal(err)
}
if _, err = keks.Encode(&buf, signed, nil); err != nil {
log.Fatal(err)
}
- if err = os.WriteFile(*cerPath, buf.Bytes(), 0o666); err != nil {
+ if err = os.WriteFile(*pubPath, buf.Bytes(), 0o666); err != nil {
log.Fatal(err)
}
}
-// certool -- dealing with KEKS-encoded certificates utility
+// keytool -- dealing with KEKS-encoded keypairs utility
// Copyright (C) 2024-2025 Sergey Matveev <stargrave@stargrave.org>
//
// This program is free software: you can redistribute it and/or modify
func usage() {
fmt.Fprintf(os.Stderr, `Usage:
- Generate certificate load:
- certool -prv PRV -cer CER [-algo ALGO] [-ku KU ...] \
+ Generate public key load:
+ keytool -prv PRV -pub PUB [-algo ALGO] [-ku KU ...] \
-subj K=V [-subj K=V ...]
Sign certificate:
- certool -cer CER -ca-prv CA-PRV -ca-cer CA-CER \
+ keytool -pub PUB -ca-prv CA-PRV -ca-pub CA-pub \
[-lifetime DAYS] [-since DATE]
Verify certificate:
- certool -verify -cer CER CA-PRV -ca-cer CA-CER0 [-ca-cer CA-CER1 ...]
+ keytool -verify -pub PUB CA-PRV -ca-pub CA-pub0 [-ca-pub CA-pub1 ...]
`)
flag.PrintDefaults()
subj="-subj what=ever"
typ="some-different-type"
-test_expect_success "$algo: cer generation" "certool \
+test_expect_success "$algo: pub generation" "keytool \
-algo $algo -ku sig $subj \
- -prv $TMPDIR/sign.prv -cer $TMPDIR/sign.cer"
+ -prv $TMPDIR/sign.prv -pub $TMPDIR/sign.pub"
dd if=/dev/urandom of=$TMPDIR/sign.data bs=300K count=1 2>/dev/null
bind="-encrypted-binding $(uuidgen)"
badBind="-encrypted-binding $(uuidgen)"
test_expect_success "$algo: signing" "sigtool \
- -prv $TMPDIR/sign.prv -cer $TMPDIR/sign.cer -type $typ \
+ -prv $TMPDIR/sign.prv -pub $TMPDIR/sign.pub -type $typ \
$bind <$TMPDIR/sign.data >$TMPDIR/sign.sig"
test_expect_success "$algo: verifying" "sigtool \
- -verify -cer $TMPDIR/sign.cer -type $typ \
+ -verify -pub $TMPDIR/sign.pub -type $typ \
<$TMPDIR/sign.sig >$TMPDIR/sign.data.got"
test_expect_success "$algo: comparing" \
"test_cmp $TMPDIR/sign.data $TMPDIR/sign.data.got"
test_expect_success "$algo: differing type" "! sigtool \
- -verify -cer $TMPDIR/sign.cer <$TMPDIR/sign.sig >/dev/null"
+ -verify -pub $TMPDIR/sign.pub <$TMPDIR/sign.sig >/dev/null"
test_expect_success "$algo: good bind" "! sigtool \
- -verify -cer $TMPDIR/sign.cer $bind <$TMPDIR/sign.sig >/dev/null"
+ -verify -pub $TMPDIR/sign.pub $bind <$TMPDIR/sign.sig >/dev/null"
test_expect_success "$algo: bad bind" "! sigtool \
- -verify -cer $TMPDIR/sign.cer $badBind <$TMPDIR/sign.sig >/dev/null"
+ -verify -pub $TMPDIR/sign.pub $badBind <$TMPDIR/sign.sig >/dev/null"
test_expect_success "$algo: detached signing" "sigtool -detached \
- -prv $TMPDIR/sign.prv -cer $TMPDIR/sign.cer -type $typ \
+ -prv $TMPDIR/sign.prv -pub $TMPDIR/sign.pub -type $typ \
<$TMPDIR/sign.data >$TMPDIR/sign.sig"
test_expect_success "$algo: detached verifying" \
"cat $TMPDIR/sign.sig $TMPDIR/sign.data |
- sigtool -detached -verify -cer $TMPDIR/sign.cer -type $typ"
+ sigtool -detached -verify -pub $TMPDIR/sign.pub -type $typ"
test_expect_success "$algo: differing type" "! sigtool -detached \
- -verify -cer $TMPDIR/sign.cer <$TMPDIR/sign.sig >/dev/null"
+ -verify -pub $TMPDIR/sign.pub <$TMPDIR/sign.sig >/dev/null"
test_expect_success "$algo: good bind" "! sigtool -detached \
- -verify -cer $TMPDIR/sign.cer $bind <$TMPDIR/sign.sig >/dev/null"
+ -verify -pub $TMPDIR/sign.pub $bind <$TMPDIR/sign.sig >/dev/null"
test_expect_success "$algo: bad bind" "! sigtool -detached \
- -verify -cer $TMPDIR/sign.cer $badBind <$TMPDIR/sign.sig >/dev/null"
+ -verify -pub $TMPDIR/sign.pub $badBind <$TMPDIR/sign.sig >/dev/null"
done
-// sigtool -- dealing with KEKS-encoded pki-signed utility
+// sigtool -- dealing with KEKS-encoded cm-signed utility
// Copyright (C) 2024-2025 Sergey Matveev <stargrave@stargrave.org>
//
// This program is free software: you can redistribute it and/or modify
"github.com/google/uuid"
"go.cypherpunks.su/keks"
- "go.cypherpunks.su/keks/pki"
- pkihash "go.cypherpunks.su/keks/pki/hash"
- "go.cypherpunks.su/keks/pki/sign"
- "go.cypherpunks.su/keks/pki/utils"
+ "go.cypherpunks.su/keks/cm"
+ cmhash "go.cypherpunks.su/keks/cm/hash"
+ "go.cypherpunks.su/keks/cm/sign"
+ "go.cypherpunks.su/keks/cm/utils"
"go.cypherpunks.su/keks/types"
)
func main() {
flag.Usage = usage
prvPath := flag.String("prv", "", "Path to private key file")
- cerPath := flag.String("cer", "", "Path to certificate file")
+ pubPath := flag.String("pub", "", "Path to public key file")
typ := flag.String("type", "data", "Set/check the load type")
verify := flag.Bool("verify", false, "Do verification")
encryptedBindingHex := flag.String("encrypted-binding", "",
}
}
- if *cerPath == "" {
- log.Fatal("no -cer is set")
+ if *pubPath == "" {
+ log.Fatal("no -pub is set")
}
- cer, err := pki.CerParse(utils.MustReadFile(*cerPath))
+ pub, err := cm.PubParse(utils.MustReadFile(*pubPath))
if err != nil {
log.Fatal(err)
}
if err != nil {
log.Fatal(err)
}
- if t != types.Magic || decoder.Iter().Magic() != pki.SignedMagic {
+ if t != types.Magic || decoder.Iter().Magic() != cm.SignedMagic {
log.Fatal("wrong magic")
}
decoder = keks.NewDecoderFromReader(stdin, nil)
if _, err = decoder.Parse(); err != nil {
log.Fatal(err)
}
- var prehash pki.SignedPrehash
- var signed pki.Signed
+ var prehash cm.SignedPrehash
+ var signed cm.Signed
err = decoder.UnmarshalStruct(&prehash)
var hasher hash.Hash
if err == nil && prehash.T == sign.PrehashT {
log.Fatal("prehash: currently only single signature support")
}
for algo := range prehash.Sigs {
- hasher = pkihash.ByName(algo)
+ hasher = cmhash.ByName(algo)
}
if hasher == nil {
log.Fatal("prehash: unsupported algorithm")
if err != nil {
log.Fatal(err)
}
- if err = pki.SignedValidate(&signed); err != nil {
+ if err = cm.SignedValidate(&signed); err != nil {
log.Fatal(err)
}
if len(signed.Sigs) == 0 {
log.Fatal("prehash: currently only single signature support")
}
sig := signed.Sigs[0]
- signer := cer.CerLoad()
+ signer := pub.PubLoad()
if signed.Load.T != *typ {
log.Fatalln("differing load type:", signed.Load.T)
}
}
}
if prehash.T == "" {
- hasher = pkihash.ByName(sig.Sign.A)
+ hasher = cmhash.ByName(sig.Sign.A)
if _, err = io.Copy(hasher, stdin); err != nil {
log.Fatal(err)
}
}
- if err = signed.CerCheckSignatureFrom(signer, &hasher); err != nil {
+ if err = signed.CertificationCheckSignatureFrom(signer, &hasher); err != nil {
log.Fatal(err)
}
} else {
log.Fatal("no -prv is set")
}
var signer sign.Iface
- signer, _, err = pki.PrvParse(utils.MustReadFile(*prvPath))
+ signer, _, err = cm.PrvParse(utils.MustReadFile(*prvPath))
if err != nil {
log.Fatal(err)
}
log.Fatal(err)
}
- if _, err = keks.Encode(os.Stdout, pki.SignedMagic, nil); err != nil {
+ if _, err = keks.Encode(os.Stdout, cm.SignedMagic, nil); err != nil {
log.Fatal(err)
}
if *detached {
log.Fatal(err)
}
} else {
- if _, err = keks.Encode(os.Stdout, pki.SignedPrehash{
+ if _, err = keks.Encode(os.Stdout, cm.SignedPrehash{
T: sign.PrehashT,
Sigs: map[string]*struct{}{signer.Algo(): nil},
}, nil); err != nil {
log.Fatal(err)
}
}
- var signed pki.Signed
+ var signed cm.Signed
signed.Load.T = *typ
- var sigTbs pki.SigTBS
+ var sigTbs cm.SigTBS
if !*noWhen {
when := time.Now().UTC().Truncate(time.Millisecond)
sigTbs.When = &when
if encryptedBinding != uuid.Nil {
sigTbs.EncryptedBinding = &encryptedBinding
}
- if err = signed.SignWith(cer.CerLoad(), signer, sigTbs); err != nil {
+ if err = signed.SignWith(pub.PubLoad(), signer, sigTbs); err != nil {
log.Fatal(err)
}
if _, err = keks.Encode(os.Stdout, signed, nil); err != nil {
-// sigtool -- dealing with KEKS-encoded pki-signed utility
+// sigtool -- dealing with KEKS-encoded cm-signed utility
// Copyright (C) 2024-2025 Sergey Matveev <stargrave@stargrave.org>
//
// This program is free software: you can redistribute it and/or modify
func usage() {
fmt.Fprintf(os.Stderr, `Usage:
- sigtool -prv PRV -cer CER [-type TYPE] [bind] <DATA >DATA.signed
- sigtool -verify -cer CER [-type TYPE] [bind] <DATA.signed >DATA
- sigtool -detached -prv PRV -cer CER [-type TYPE] [bind] <DATA >DATA.signature
- sigtool -detached -verify -cer CER [-type TYPE] [bind] <(cat DATA.signature DATA)
+ sigtool -prv PRV -pub PUB [-type TYPE] [bind] <DATA >DATA.signed
+ sigtool -verify -pub PUB [-type TYPE] [bind] <DATA.signed >DATA
+ sigtool -detached -prv PRV -pub PUB [-type TYPE] [bind] <DATA >DATA.signature
+ sigtool -detached -verify -pub PUB [-type TYPE] [bind] <(cat DATA.signature DATA)
"bind" is optional -encrypted-binding flag.
DATA.signed holds completely encapsulated DATA.
--- /dev/null
+// GoKEKS/CM -- KEKS-encoded cryptographic messages
+package cm
+++ ed25519/ed25519.go 2024-12-03 11:07:51.892841000 +0300
@@ -20,11 +20,12 @@
"crypto"
- "go.cypherpunks.su/keks/pki/ed25519-blake2b/edwards25519"
+ "go.cypherpunks.su/keks/cm/ed25519-blake2b/edwards25519"
cryptorand "crypto/rand"
- "crypto/sha512"
"crypto/subtle"
-// GoKEKS/PKI -- PKI-related capabilities based on KEKS encoded formats
+// 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
import (
"hash"
- "go.cypherpunks.su/keks/pki/hash/merkle"
+ "go.cypherpunks.su/keks/cm/hash/merkle"
"golang.org/x/crypto/blake2b"
)
-// GoKEKS/PKI -- PKI-related capabilities based on KEKS encoded formats
+// 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
import (
"crypto/rand"
- "go.cypherpunks.su/keks/pki/ed25519-blake2b/ed25519"
+ "go.cypherpunks.su/keks/cm/ed25519-blake2b/ed25519"
)
func NewKeypair() (signer *Signer, prv, pub []byte, err error) {
# That script copies the library (tested on 1.23.3) and patches it to
# use BLAKE2b hash.
-modname=go.cypherpunks.su/keks/pki/ed25519-blake2b
+modname=go.cypherpunks.su/keks/cm/ed25519-blake2b
go mod init $modname
dst=$PWD
cd $(go env GOROOT)/src
-// GoKEKS/PKI -- PKI-related capabilities based on KEKS encoded formats
+// 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
"io"
"runtime"
- "go.cypherpunks.su/keks/pki/ed25519-blake2b/ed25519"
- "go.cypherpunks.su/keks/pki/hash/merkle"
+ "go.cypherpunks.su/keks/cm/ed25519-blake2b/ed25519"
+ "go.cypherpunks.su/keks/cm/hash/merkle"
"golang.org/x/crypto/blake2b"
- "go.cypherpunks.su/keks/pki/sign"
+ "go.cypherpunks.su/keks/cm/sign"
)
type Signer struct {
-// GoKEKS/PKI -- PKI-related capabilities based on KEKS encoded formats
+// 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
"crypto"
"errors"
- "go.cypherpunks.su/keks/pki/ed25519-blake2b/ed25519"
+ "go.cypherpunks.su/keks/cm/ed25519-blake2b/ed25519"
)
func Verify(pub, signed, signature []byte) (valid bool, err error) {
-module go.cypherpunks.su/keks/pki
+module go.cypherpunks.su/keks/cm
go 1.24
require (
github.com/google/uuid v1.6.0
- go.cypherpunks.su/gogost/v6 v6.0.1
+ go.cypherpunks.su/gogost/v6 v6.1.0
)
require (
--- /dev/null
+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=
+go.cypherpunks.su/balloon/v3 v3.0.0/go.mod h1:ftUPgriajbLsU16feNNHht6cuOwxCK6MGnDK3lLQhgM=
+go.cypherpunks.su/gogost/v6 v6.1.0 h1:RJHFxDZ2j/TIfHXGn4AG0fTDg19GEX/oVFAgMvLCIPM=
+go.cypherpunks.su/gogost/v6 v6.1.0/go.mod h1:cj9i0r80PN7jrwMqBAWhaY8JetCeg4x5jjnZsVRkaPI=
+golang.org/x/crypto v0.32.0/go.mod h1:ZnnJkOaASj8g0AjIduWNlq2NRxL0PlBrbKVyZ6V/Ugc=
-// GoKEKS/PKI -- PKI-related capabilities based on KEKS encoded formats
+// 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
-// GoKEKS/PKI -- PKI-related capabilities based on KEKS encoded formats
+// 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
import (
"hash"
- "go.cypherpunks.su/keks/pki/hash/merkle"
+ "go.cypherpunks.su/keks/cm/hash/merkle"
)
const (
-// GoKEKS/PKI -- PKI-related capabilities based on KEKS encoded formats
+// 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
-// GoKEKS/PKI -- PKI-related capabilities based on KEKS encoded formats
+// 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
"go.cypherpunks.su/gogost/v6/gost34112012256"
"go.cypherpunks.su/gogost/v6/gost34112012512"
- "go.cypherpunks.su/keks/pki/hash/merkle"
- "go.cypherpunks.su/keks/pki/sign"
+ "go.cypherpunks.su/keks/cm/hash/merkle"
+ "go.cypherpunks.su/keks/cm/sign"
)
type Signer struct {
-// GoKEKS/PKI -- PKI-related capabilities based on KEKS encoded formats
+// 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
"go.cypherpunks.su/gogost/v6/gost3410"
"go.cypherpunks.su/gogost/v6/gost34112012256"
"go.cypherpunks.su/gogost/v6/gost34112012512"
- "go.cypherpunks.su/keks/pki/utils"
+ "go.cypherpunks.su/keks/cm/utils"
)
func Verify(algo string, pub, signed, signature []byte) (valid bool, err error) {
-// GoKEKS/PKI -- PKI-related capabilities based on KEKS encoded formats
+// 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
"go.cypherpunks.su/gogost/v6/gost34112012512"
"golang.org/x/crypto/blake2b"
- ed25519blake2b "go.cypherpunks.su/keks/pki/ed25519-blake2b"
- "go.cypherpunks.su/keks/pki/gost"
- "go.cypherpunks.su/keks/pki/hash/merkle"
+ ed25519blake2b "go.cypherpunks.su/keks/cm/ed25519-blake2b"
+ "go.cypherpunks.su/keks/cm/gost"
+ "go.cypherpunks.su/keks/cm/hash/merkle"
)
const (
-// GoKEKS/PKI -- PKI-related capabilities based on KEKS encoded formats
+// 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
-// GoKEKS/PKI -- PKI-related capabilities based on KEKS encoded formats
+// 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
-// GoKEKS/PKI -- PKI-related capabilities based on KEKS encoded formats
+// 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
-// GoKEKS/PKI -- PKI-related capabilities based on KEKS encoded formats
+// 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
"hash"
"io"
- "go.cypherpunks.su/keks/pki/hash/merkle"
+ "go.cypherpunks.su/keks/cm/hash/merkle"
)
type SHAKE struct {
-// GoKEKS/PKI -- PKI-related capabilities based on KEKS encoded formats
+// 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
-// GoKEKS/PKI -- PKI-related capabilities based on KEKS encoded formats
+// 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
// 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 pki
+package cm
import (
"errors"
"fmt"
"go.cypherpunks.su/keks"
- ed25519blake2b "go.cypherpunks.su/keks/pki/ed25519-blake2b"
- "go.cypherpunks.su/keks/pki/gost"
- "go.cypherpunks.su/keks/pki/sign"
+ ed25519blake2b "go.cypherpunks.su/keks/cm/ed25519-blake2b"
+ "go.cypherpunks.su/keks/cm/gost"
+ "go.cypherpunks.su/keks/cm/sign"
)
// Parse private key contained in AV KEKS-encoded structure.
{
var magic keks.Magic
magic, data = keks.StripMagic(data)
- if magic != "" && magic != PrvKeyMagic {
+ if magic != "" && magic != PrvMagic {
err = errors.New("wrong magic")
return
}
-// GoKEKS/PKI -- PKI-related capabilities based on KEKS encoded formats
+// 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
// 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 pki
+package cm
import (
"bytes"
"github.com/google/uuid"
"go.cypherpunks.su/keks"
- ed25519blake2b "go.cypherpunks.su/keks/pki/ed25519-blake2b"
- "go.cypherpunks.su/keks/pki/gost"
- "go.cypherpunks.su/keks/pki/sign"
+ ed25519blake2b "go.cypherpunks.su/keks/cm/ed25519-blake2b"
+ "go.cypherpunks.su/keks/cm/gost"
+ "go.cypherpunks.su/keks/cm/sign"
)
const (
KUSig = "sig" // Signing-capable key usage
KUKEM = "kem" // Key-encapsulation-mechanism key usage
- CerMagic = keks.Magic("pki/cer")
+ PubMagic = keks.Magic("cm/pub")
)
var (
Id uuid.UUID `keks:"id"`
}
-// Certificate load (contents).
-type CerLoad struct {
+// Public key load.
+type PubLoad struct {
KU *map[string]*struct{} `keks:"ku,omitempty"`
Subj map[string]string `keks:"sub"`
Crit *[]map[string]any `keks:"crit,omitempty"`
Pub []Pub `keks:"pub"`
}
-// Parse Signed contents as CerLoad (certificate) and check its
-// signatures necessary structure. signed.Load.V will hold the CerLoad in
-// case of success.
-func (signed *Signed) CerParse() error {
- if signed.Load.T != "cer" {
- return errors.New("CerParse: wrong load type")
+// Parse Signed contents as PubLoad (certificate) and check its
+// signatures necessary structure. signed.Load.V will hold the
+// PubLoad in case of success.
+func (signed *Signed) PubParse() error {
+ if signed.Load.T != "pub" {
+ return errors.New("PubParse: wrong load type")
}
for _, sig := range signed.Sigs {
if sig.TBS.CID == nil {
- return errors.New("CerParse: missing cid")
+ return errors.New("PubParse: missing cid")
}
if sig.TBS.Exp == nil {
- return errors.New("CerParse: missing exp")
+ return errors.New("PubParse: missing exp")
}
}
if signed.Load.V == nil {
- return errors.New("CerParse: missing /load/v")
+ return errors.New("PubParse: missing /load/v")
}
- var load CerLoad
+ var load PubLoad
var err error
if v, ok := (*signed.Load.V).(map[string]any); ok {
err = keks.Map2Struct(&load, v)
} else {
- err = errors.New("CerParse: wrong /load/v")
+ err = errors.New("PubParse: wrong /load/v")
}
if err != nil {
return err
}
if load.KU != nil {
if len(*load.KU) == 0 {
- return errors.New("CerParse: empty ku")
+ return errors.New("PubParse: empty ku")
}
for _, v := range *load.KU {
if v != nil {
- return errors.New("CerParse: non-nil ku value")
+ return errors.New("PubParse: non-nil ku value")
}
}
}
if len(load.Subj) == 0 {
- return errors.New("CerParse: empty sub")
+ return errors.New("PubParse: empty sub")
}
if load.Crit != nil {
if len(*load.Crit) == 0 {
- return errors.New("CerParse: empty crit")
+ return errors.New("PubParse: empty crit")
}
- return errors.New("CerParse: currently no critical extensions are supported")
+ return errors.New("PubParse: currently no critical extensions are supported")
}
if len(load.Pub) == 0 {
- return errors.New("CerParse: empty pub")
+ return errors.New("PubParse: empty pub")
}
for _, pub := range load.Pub {
if len(pub.A) == 0 || len(pub.V) == 0 || pub.Id == uuid.Nil {
- return errors.New("CerParse: non-filled pub")
+ return errors.New("PubParse: non-filled pub")
}
}
return nil
}
-// Parse KEKS-encoded data as Signed with the CerLoad (certificate) contents.
-func CerParse(data []byte) (signed *Signed, err error) {
+// Parse KEKS-encoded data as Signed with the PubLoad (certificate) contents.
+func PubParse(data []byte) (signed *Signed, err error) {
{
var magic keks.Magic
magic, data = keks.StripMagic(data)
- if magic != "" && magic != CerMagic {
+ if magic != "" && magic != PubMagic {
err = errors.New("wrong magic")
return
}
if err != nil {
return
}
- err = signed.CerParse()
+ err = signed.PubParse()
return
}
-// Check if cer certificate has desired ku capability.
-func (cer *CerLoad) Can(ku string) (yes bool) {
- if cer.KU == nil {
+// Check if public key has desired ku capability.
+func (pub *PubLoad) Can(ku string) (yes bool) {
+ if pub.KU == nil {
return false
}
- _, yes = (*cer.KU)[ku]
+ _, yes = (*pub.KU)[ku]
return
}
-// Sign the current Signed, having CerLoad payload with the provided
-// parent's CerLoad and prv key. Certificate's CID will be automatically
+// Sign the provided Signed, having PubLoad payload with the provided
+// parent's PubLoad and prv key. Certification CID will be automatically
// generated UUIDv7. since and till times must not have nanoseconds part.
-func (signed *Signed) CerIssueWith(
- parent *CerLoad,
+func (signed *Signed) CertifyWith(
+ parent *PubLoad,
prv sign.Iface,
since, till time.Time,
) error {
// Verify signature of signed data. ErrSigInvalid will be returned in
// case of invalid signature.
-func (cer *CerLoad) CheckSignature(algo string, signed, signature []byte) (err error) {
- if !cer.Can(KUSig) || len(cer.Pub) != 1 {
- err = errors.New("cer can not sign")
+func (pub *PubLoad) CheckSignature(algo string, signed, signature []byte) (err error) {
+ if !pub.Can(KUSig) || len(pub.Pub) != 1 {
+ err = errors.New("pub can not sign")
return
}
- pub := cer.Pub[0]
+ key := pub.Pub[0]
var valid bool
- switch pub.A {
+ switch key.A {
case Ed25519BLAKE2b:
if algo != Ed25519BLAKE2b {
return ErrBadSigAlgo
}
- valid, err = ed25519blake2b.Verify(pub.V, signed, signature)
+ valid, err = ed25519blake2b.Verify(key.V, signed, signature)
if !valid {
err = ErrSigInvalid
}
case GOST3410256A, GOST3410512C:
- if algo != pub.A {
+ if algo != key.A {
return ErrBadSigAlgo
}
- valid, err = gost.Verify(pub.A, pub.V, signed, signature)
+ valid, err = gost.Verify(key.A, key.V, signed, signature)
if !valid {
err = ErrSigInvalid
}
// Verify signature of signed data, by providing prehashed data.
// ErrSigInvalid will be returned in case of invalid signature.
-func (cer *CerLoad) CheckSignaturePrehash(
+func (pub *PubLoad) CheckSignaturePrehash(
algo string,
prehash, signature []byte,
) (err error) {
- if !cer.Can(KUSig) || len(cer.Pub) != 1 {
- err = errors.New("cer can not sign")
+ if !pub.Can(KUSig) || len(pub.Pub) != 1 {
+ err = errors.New("pub can not sign")
return
}
- pub := cer.Pub[0]
+ key := pub.Pub[0]
var valid bool
- switch pub.A {
+ switch key.A {
case Ed25519BLAKE2b:
switch algo {
case Ed25519PhBLAKE2b:
default:
return ErrBadSigAlgo
}
- valid, err = ed25519blake2b.VerifyPrehash(pub.V, prehash, signature)
+ valid, err = ed25519blake2b.VerifyPrehash(key.V, prehash, signature)
if !valid {
err = ErrSigInvalid
}
default:
return ErrBadSigAlgo
}
- valid, err = gost.VerifyPrehash(pub.A, pub.V, prehash, signature)
+ valid, err = gost.VerifyPrehash(key.A, key.V, prehash, signature)
if !valid {
err = ErrSigInvalid
}
return
}
-// Verify Signed CerLoad certificate's signature with provided parent.
+// Verify Signed PubLoad certification signature with provided parent.
// If prehasher is specified, then prehashed signature mode is used.
// Currently only single signature can be verified.
-func (signed *Signed) CerCheckSignatureFrom(
- parent *CerLoad,
+func (signed *Signed) CertificationCheckSignatureFrom(
+ parent *PubLoad,
prehasher *hash.Hash,
) (err error) {
if len(signed.Sigs) != 1 {
}
}
-// Get CerLoad from Signed.
+// Get PubLoad from Signed.
// Returns nil if Signed does not hold it (or it is not yet parsed).
-func (signed *Signed) CerLoad() *CerLoad {
- if signed.Load.T != "cer" || signed.Load.V == nil {
+func (signed *Signed) PubLoad() *PubLoad {
+ if signed.Load.T != "pub" || signed.Load.V == nil {
return nil
}
- l, ok := (*signed.Load.V).(CerLoad)
+ l, ok := (*signed.Load.V).(PubLoad)
if ok {
return &l
}
return nil
}
-// Verify signed Signed CerLoad certificate against cers chain of
-// certificate authority ones at specified point of time t.
-func (signed *Signed) CerVerify(cers []*Signed, t time.Time) (err error) {
+// Verify signed Signed PubLoad certification against pubs chain of
+// public keys at specified point of time t.
+func (signed *Signed) CertificationVerify(pubs []*Signed, t time.Time) (err error) {
{
exp := *(signed.Sigs[0].TBS.Exp)
if t.Before(exp[0]) || t.Equal(exp[0]) {
- err = errors.New("cer is not active")
+ err = errors.New("pub is not active")
return
}
if t.After(exp[1]) || t.Equal(exp[1]) {
- err = errors.New("cer is expired")
+ err = errors.New("pub is expired")
return
}
}
sid := signed.Sigs[0].TBS.SID
- if sid == signed.CerLoad().Pub[0].Id {
- return signed.CerCheckSignatureFrom(signed.CerLoad(), nil)
+ if sid == signed.PubLoad().Pub[0].Id {
+ return signed.CertificationCheckSignatureFrom(signed.PubLoad(), nil)
}
- idToCer := make(map[uuid.UUID]*Signed, len(cers))
- for _, cer := range cers {
- cerLoad := cer.CerLoad()
- if !cerLoad.Can(KUSig) || len(cerLoad.Pub) != 1 {
- err = errors.New("cer can not sign")
+ idToPub := make(map[uuid.UUID]*Signed, len(pubs))
+ for _, cer := range pubs {
+ pubLoad := cer.PubLoad()
+ if !pubLoad.Can(KUSig) || len(pubLoad.Pub) != 1 {
+ err = errors.New("pub can not sign")
return
}
- idToCer[cerLoad.Pub[0].Id] = cer
+ idToPub[pubLoad.Pub[0].Id] = cer
}
- signer := idToCer[sid]
+ signer := idToPub[sid]
if signer == nil {
- err = fmt.Errorf("no cer found for sid: %v", signed.Sigs[0].TBS.SID)
+ err = fmt.Errorf("no pub found for sid: %v", signed.Sigs[0].TBS.SID)
return
}
- err = signed.CerCheckSignatureFrom(signer.CerLoad(), nil)
+ err = signed.CertificationCheckSignatureFrom(signer.PubLoad(), nil)
if err != nil {
return
}
- return signer.CerVerify(cers, t)
+ return signer.CertificationVerify(pubs, t)
}
-// GoKEKS/PKI -- PKI-related capabilities based on KEKS encoded formats
+// 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
// 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 pki
+package cm
import (
"bytes"
"github.com/google/uuid"
"go.cypherpunks.su/keks"
- "go.cypherpunks.su/keks/pki/sign"
+ "go.cypherpunks.su/keks/cm/sign"
)
-const SignedMagic = keks.Magic("pki/signed")
+const SignedMagic = keks.Magic("cm/signed")
type SignedPrehash struct {
Sigs map[string]*struct{} `keks:"sigs"`
type Sig struct {
TBS SigTBS `keks:"tbs,omitempty"`
- CerLoc *[]string `keks:"cer-loc,omitempty"`
+ PubLoc *[]string `keks:"pub-loc,omitempty"`
Sign AV `keks:"sign"`
}
type Signed struct {
- Cers *[]*Signed `keks:"certs,omitempty"`
Load SignedLoad `keks:"load"`
+ Pubs *[]*Signed `keks:"pubs,omitempty"`
Sigs []*Sig `keks:"sigs"`
}
-// Validate parsed pki-signed structure.
+// Validate parsed cm-signed structure.
func SignedValidate(signed *Signed) (err error) {
- if signed.Cers != nil {
- if len(*signed.Cers) == 0 {
- err = errors.New("SignedParse: empty /certs")
+ if signed.Pubs != nil {
+ if len(*signed.Pubs) == 0 {
+ err = errors.New("SignedParse: empty /pubs")
return
}
- for _, cer := range *signed.Cers {
- err = cer.CerParse()
+ for _, pub := range *signed.Pubs {
+ err = pub.PubParse()
if err != nil {
return
}
}
}
for _, sig := range signed.Sigs {
- if sig.CerLoc != nil && len(*sig.CerLoc) == 0 {
- err = errors.New("SignedParse: empty cer-loc")
+ if sig.PubLoc != nil && len(*sig.PubLoc) == 0 {
+ err = errors.New("SignedParse: empty pub-loc")
return
}
if sig.TBS.Exp != nil {
return
}
-// Parse pki-signed from KEKS-encoded data. This is just a wrapper over
+// Parse cm-signed from KEKS-encoded data. This is just a wrapper over
// SignedParseItem.
func SignedParse(data []byte) (*Signed, error) {
{
}
// Sign Signed's contents and sigTBS corresponding data with the
-// provided prv signer, having parent certificate. Signature is appended
-// to the signed.Sigs. parent certificate must have "sig" key-usage.
-func (signed *Signed) SignWith(parent *CerLoad, prv sign.Iface, sigTBS SigTBS) (err error) {
+// provided prv signer, having parent certififer. Signature is appended
+// to the signed.Sigs. parent must have "sig" key-usage.
+func (signed *Signed) SignWith(parent *PubLoad, prv sign.Iface, sigTBS SigTBS) (err error) {
if !parent.Can(KUSig) || len(parent.Pub) != 1 {
return errors.New("parent can not sign")
}
-module go.cypherpunks.su/keks/pki/sntrup4591761-x25519
+module go.cypherpunks.su/keks/cm/sntrup4591761-x25519
go 1.24
-// GoKEKS/PKI -- PKI-related capabilities based on KEKS encoded formats
+// 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
-// GoKEKS/PKI -- PKI-related capabilities based on KEKS encoded formats
+// 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
+++ /dev/null
-package pki
-
-import (
- "go.cypherpunks.su/keks"
- ed25519blake2b "go.cypherpunks.su/keks/pki/ed25519-blake2b"
- "go.cypherpunks.su/keks/pki/gost"
- mceliece6960119x25519 "go.cypherpunks.su/keks/pki/mceliece6960119-x25519"
- sntrup4591761x25519 "go.cypherpunks.su/keks/pki/sntrup4591761-x25519"
-)
-
-const (
- BalloonBLAKE2bHKDF = "balloon-blake2b-hkdf"
- ChaCha20Poly1305 = "chacha20poly1305"
- ClassicMcEliece6960119X25519 = mceliece6960119x25519.ClassicMcEliece6960119X25519
- ClassicMcEliece6960119X25519HKDFSHAKE256 = mceliece6960119x25519.ClassicMcEliece6960119X25519HKDFSHAKE256
- Ed25519BLAKE2b = ed25519blake2b.Ed25519BLAKE2b
- Ed25519PhBLAKE2b = ed25519blake2b.Ed25519PhBLAKE2b
- Ed25519PhBLAKE2bMerkle = ed25519blake2b.Ed25519PhBLAKE2bMerkle
- GOST3410256A = gost.GOST3410256A
- GOST3410256AMerkle = gost.GOST3410256AMerkle
- GOST3410512C = gost.GOST3410512C
- GOST3410512CMerkle = gost.GOST3410512CMerkle
- SNTRUP4591761X25519 = sntrup4591761x25519.SNTRUP4591761X25519
- SNTRUP4591761X25519HKDFBLAKE2b = sntrup4591761x25519.SNTRUP4591761X25519HKDFBLAKE2b
-
- EncryptedMagic = keks.Magic("pki/encryptd")
- HashedMagic = keks.Magic("pki/hashed")
- PrvKeyMagic = keks.Magic("pki/prvkey")
-)
+++ /dev/null
-#!/bin/sh
-
-test_description="Check that basic GOST-related functionality works"
-. $SHARNESS_TEST_SRCDIR/sharness.sh
-
-TMPDIR=${TMPDIR:-/tmp}
-
-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" "certool \
- -algo $caAlgo \
- -ku sig $subj \
- -prv $TMPDIR/ca.prv -cer $TMPDIR/ca.cer"
-test_expect_success "$caAlgo: CA generation" "certool \
- -cer $TMPDIR/ca.cer \
- -ca-prv $TMPDIR/ca.prv -ca-cer $TMPDIR/ca.cer"
-test_expect_success "$caAlgo: CA regeneration" "certool \
- -cer $TMPDIR/ca.cer \
- -ca-prv $TMPDIR/ca.prv -ca-cer $TMPDIR/ca.cer"
-test_expect_success "$caAlgo: CA self-signature" "certool \
- -ca-cer $TMPDIR/ca.cer \
- -cer $TMPDIR/ca.cer \
- -verify"
-
-subj="-subj CN=SubCA -subj C=RU"
-test_expect_success "$eeAlgo: SubCA load generation" "certool \
- -algo $eeAlgo \
- -ku sig $subj \
- -prv $TMPDIR/subca.prv -cer $TMPDIR/subca.cer"
-test_expect_success "$eeAlgo: SubCA generation" "certool \
- -cer $TMPDIR/subca.cer \
- -ca-cer $TMPDIR/ca.cer -ca-prv $TMPDIR/ca.prv"
-test_expect_success "$eeAlgo: SubCA signature" "certool \
- -ca-cer $TMPDIR/ca.cer \
- -cer $TMPDIR/subca.cer \
- -verify"
-
-subj="-subj CN=EE -subj C=RU"
-test_expect_success "$eeAlgo: EE load generation" "certool \
- -algo $eeAlgo $subj \
- -prv $TMPDIR/ee.prv -cer $TMPDIR/ee.cer"
-test_expect_success "$eeAlgo: EE generation" "certool \
- -ca-prv $TMPDIR/subca.prv -ca-cer $TMPDIR/subca.cer \
- -cer $TMPDIR/ee.cer"
-test_expect_success "$eeAlgo: EE chain" "certool \
- -ca-cer $TMPDIR/ca.cer \
- -ca-cer $TMPDIR/subca.cer \
- -cer $TMPDIR/ee.cer \
- -verify"
-
-done
-
-test_done
+++ /dev/null
-// GoKEKS/PKI provides PKI-related capabilities based on KEKS encoded formats
-package pki
+++ /dev/null
-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=
-go.cypherpunks.su/gogost/v6 v6.0.1 h1:PFjBnUmfdbx7L5R6hRt/+ZgGwWx45wTIWezFSgmknrs=
-go.cypherpunks.su/gogost/v6 v6.0.1/go.mod h1:qJm0B7KJY4/OD5nYqL10kXY09dUwu2AfwSPu72Otngs=
-golang.org/x/crypto v0.26.0 h1:RrRspgV4mU+YwB4FYnuBoKsUapNIL5cohGAmSH3azsw=
@node Floats
+@cindex floats
@cindex FLOAT16
@cindex FLOAT32
@cindex FLOAT64
@node LIST
+@cindex LIST
@cindex EOC
@section LIST
@multitable @columnfractions .5 .5
-@item MAGIC(pki/cer) @tab @code{4B454B53 706B692F636572 0000000000}
-@item MAGIC(pki/signed) @tab @code{4B454B53 706B692F7369676E6564 0000}
-@item MAGIC(pki/encryptd) @tab @code{4B454B53 706B692F656E637279707464}
+@item MAGIC(cm/pub) @tab @code{4B454B53 636D2F707562 000000000000}
+@item MAGIC(cm/signed) @tab @code{4B454B53 636D2F7369676E6564 000000}
+@item MAGIC(cm/encrypted) @tab @code{4B454B53 636D2F656E63727970746564}
@end multitable
ai = text ; algorithm identifier
-pki-encrypted = {
+cm-encrypted = {
dem: dem,
kem: [+ kem],
bind: uuid,
-@node pki-encrypted
-@cindex pki-encrypted
-@section pki-encrypted format
+@node cm-encrypted
+@cindex cm-encrypted
+@section cm-encrypted format
-Stored in a file, it should begin with "pki/encryptd" @ref{Magic, magic}.
+Stored in a file, it should begin with "cm/encrypted" @ref{Magic, magic}.
@verbatiminclude format/encrypted.cddl
@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{pki-encrypted} structure.
+for example just following the @code{cm-encrypted} structure.
CEK is encapsulated in @code{/kem/*} entries (key encapsulation
mechanism), using @code{/kem/*/a} algorithm. @code{/kem/*/cek} field
contains an encrypted CEK.
-If KEM uses public-key based cryptography, then recipient's public
-key(s) should be provided by @ref{cer, certificate}, which may lack the
+If KEM uses public-key based cryptography, then recipient's
+@ref{cm-pub, public key}(s) should be provided, which may lack the
signatures at all. Optional @code{/kem/*/to}, public key's identifier,
may provide a hint for quickly searching for the key on the recipient's
side.
@code{/bind} value can be used to bind the encrypted
-@code{@ref{pki-signed, pki-signed}} to the envelope.
+@code{@ref{cm-signed, cm-signed}} to the envelope.
Either UUIDv4 or UUIDv7 are recommended.
-@node pki-encrypted-chacha20poly1305
-@subsection pki-encrypted with ChaCha20-Poly1305 DEM
+@node cm-encrypted-chacha20poly1305
+@cindex cm-encrypted-chacha20poly1305
+@subsection Encrypted data with ChaCha20-Poly1305 DEM
@code{/dem/a} equals to "chacha20poly1305". Data is split on 64 KiB
chunks which are encrypted the following way:
@code{/ciphertext}'s chunk length equals to 16+64KiB+16 bytes.
-@node pki-encrypted-kuznechik-ctracpkm-hmac-hkdf
-@subsection pki-encrypted-kuznechik-ctracpkm-hmac-hkdf
+@node cm-encrypted-kuznechik-ctracpkm-hmac-hkdf
+@cindex cm-encrypted-kuznechik-ctracpkm-hmac-hkdf
+@subsection Encrypted data with Kuznechik-CTR-ACPKM-HMAC-HKDF DEM
@code{/dem/a} equals to "kuznechik-ctracpkm-hmac-hkdf".
@code{/dem/seed} contains 16 bytes for the HKDF invocation below.
@verbatim
Kenc, Kauth = HKDF-Extract(Streebog-512,
- salt="keks/pki/encrypted/kuznechik-ctracpkm-hmac-hkdf",
+ salt="keks/cm/encrypted/kuznechik-ctracpkm-hmac-hkdf",
secret=seed || CEK)
@end verbatim
@code{/ciphertext}'s chunk length equals to 64KiB bytes.
-@node pki-encrypted-balloon-blake2b-hkdf
-@subsection pki-encrypted with Balloon-BLAKE2b+HKDF-BLAKE2b KEM
+@node cm-encrypted-balloon-blake2b-hkdf
+@cindex cm-encrypted-balloon-blake2b-hkdf
+@subsection Encrypted data with Balloon-BLAKE2b+HKDF-BLAKE2b KEM
@code{/kem/*/a} equals to "balloon-blake2b-hkdf".
Recipient map must also contain additional fields:
@verbatim
KEK = HKDF-Extract(BLAKE2b-256,
- salt="keks/pki/encrypted/balloon-blake2b-hkdf",
+ salt="keks/cm/encrypted/balloon-blake2b-hkdf",
secret=balloon(BLAKE2b-256, password, bind || salt, s, t, p))
ChaCha20-Poly1305(data=16*0x00 || CEK, key=KEK, nonce=12*0x00, ad="")
@end verbatim
-@node pki-encrypted-gost3410-hkdf-kexp15
-@subsection pki-encrypted-gost3410-hkdf-kexp15
+@node cm-encrypted-gost3410-hkdf-kexp15
+@cindex cm-encrypted-gost3410-hkdf-kexp15
+@subsection Encrypted data with GOST R 34.10-HKDF-KExp15 KEM
@code{/kem/*/a} equals to "gost3410-hkdf-kexp15".
Recipient map must also contain additional fields:
@verbatim
KEKenv, KEKauth = HKDF-Extract(Streebog-512,
- salt="keks/pki/encrypted/gost3410-hkdf-kexp15",
+ salt="keks/cm/encrypted/gost3410-hkdf-kexp15",
secret=bind || VKO(...))
KExp15(KEKenc, KEKauth, IV, CEK):
return CTR(Kenc, CEK+CMAC(Kauth, IV+CEK), IV=IV)
@end verbatim
-@node pki-encrypted-sntrup4591761-x25519-hkdf-blake2b
-@subsection pki-encrypted with SNTRUP4591761+x25519+HKDF-BLAKE2b KEM
+@node cm-encrypted-sntrup4591761-x25519-hkdf-blake2b
+@cindex cm-encrypted-sntrup4591761-x25519-hkdf-blake2b
+@subsection Encrypted data with SNTRUP4591761+x25519+HKDF-BLAKE2b KEM
@code{/kem/*/a} equals to "sntrup4591761-x25519-hkdf-blake2b".
- Recipient certificate with
- @ref{cer-sntrup4591761-x25519, @code{sntrup4591761-x25519}} public key
- must be used. It should have "kem" key usage set.
+ Recipient public key with
+ @ref{cm-pub-sntrup4591761-x25519, @code{sntrup4591761-x25519}}
+ algorithm must be used. It should have "kem" key usage set.
Recipient map must also contain additional field:
@code{/kem/*/encap: bytes} -- concatenation of 1047 bytes of Streamlined
@verbatim
KEK = HKDF-Extract(BLAKE2b-256,
- salt="keks/pki/encrypted/sntrup4591761-x25519-hkdf-blake2b",
+ salt="keks/cm/encrypted/sntrup4591761-x25519-hkdf-blake2b",
secret=bind ||
sntrup4591761-sender-ciphertext ||
x25519-sender-public-key ||
ChaCha20-Poly1305(data=16*0x00 || CEK, key=KEK, nonce=12*0x00, ad="")
@end verbatim
-@node pki-encrypted-mceliece6960119-x25519-hkdf-shake256
-@subsection pki-encrypted with Classic McEliece 6960119+x25519+HKDF-SHAKE256 KEM
+@node cm-encrypted-mceliece6960119-x25519-hkdf-shake256
+@cindex cm-encrypted-mceliece6960119-x25519-hkdf-shake256
+@subsection Encrypted data with Classic McEliece 6960119+x25519+HKDF-SHAKE256 KEM
@code{/kem/*/a} equals to "mceliece6960119-x25519-hkdf-shake256".
- Recipient certificate with
- @ref{cer-mceliece6960119-x25519, @code{mceliece6960119-x25519}} public key
- must be used. It should have "kem" key usage set.
+ Recipient public key with
+ @ref{cm-pub-mceliece6960119-x25519, @code{mceliece6960119-x25519}}
+ algorithm must be used. It should have "kem" key usage set.
Recipient map must also contain additional field:
@code{/kem/*/encap: bytes} -- concatenation of 194 bytes of
@verbatim
KEK = HKDF-Extract(SHAKE256,
- salt="keks/pki/encrypted/mceliece6960119-x25519-hkdf-shake256",
+ salt="keks/cm/encrypted/mceliece6960119-x25519-hkdf-shake256",
secret=bind ||
mceliece6960119-sender-ciphertext ||
x25519-sender-public-key ||
ai = text ; algorithm identifier
-pki-hashed = {
+cm-hashed = {
a: [+ ai],
t: text, ; type of the content
v: bytes / text / blob / map / list, ; content itself
-@node pki-hashed
-@cindex pki-hashed
-@section pki-hashed format
+@node cm-hashed
+@cindex cm-hashed
+@section cm-hashed format
Integrity protected container, CMS'es DigestedData analogue.
-Stored in a file, it should begin with "pki/hashed" @ref{Magic, magic}.
+Stored in a file, it should begin with "cm/hashed" @ref{Magic, magic}.
@verbatiminclude format/hashed.cddl
Merkle trees are very convenient way to parallelise data hashing.
@url{https://datatracker.ietf.org/doc/html/rfc9162, RFC 9162} is used as
- a base for all Merkle-tree based hashers. By default 128KiB chunks are
-used.
+ a base for all Merkle-tree based hashers.
-@node pki-hashed-blake2b
-@subsection pki-hashed with BLAKE2b
+ By default 128KiB chunks are used.
+
+@node cm-hashed-blake2b
+@cindex cm-hashed-blake2b
+@subsection Hashed data with BLAKE2b
@url{https://www.blake2.net/, BLAKE2b} with
512-bit output has @code{blake2b} algorithm identifier.
256-bit output has @code{blake2b256} algorithm identifier.
-@node pki-hashed-blake2b-merkle
-@subsection pki-hashed with BLAKE2b in Merkle-tree mode
+@node cm-hashed-blake2b-merkle
+@cindex cm-hashed-blake2b-merkle
+@subsection Hashed data with BLAKE2b in Merkle-tree mode
BLAKE2b-512 is initialised with either "LEAF" or "NODE" keys,
instead of using @code{0x00}/@code{0x01} constants prepending to the
@code{blake2b-merkle} algorithm identifier is used.
-@node pki-hashed-blake3
-@subsection pki-hashed with BLAKE3
+@node cm-hashed-blake3
+@cindex cm-hashed-blake3
+@subsection Hashed data with BLAKE3
@url{https://github.com/BLAKE3-team/BLAKE3/, BLAKE3} with fixed
256-bit output has @code{blake3} algorithm identifier.
-@node pki-hashed-sha2
-@subsection pki-hashed with SHA2
+@node cm-hashed-sha2
+@cindex cm-hashed-sha2
+@subsection Hashed data with SHA2
SHA2-256 has @code{sha2-256} algorithm identifier.
SHA2-512 has @code{sha2-512} algorithm identifier.
-@node pki-hashed-shake
-@subsection pki-hashed with SHAKE
+@node cm-hashed-shake
+@cindex cm-hashed-shake
+@subsection Hashed data with SHAKE
@url{https://keccak.team/, SHAKE} XOF function with fixed
256 (SHAKE128) or 512 (SHAKE256) bit output.
@code{shake128}, @code{shake256} algorithm identifiers are used.
-@node pki-hashed-shake-merkle
-@subsection pki-hashed with SHAKE in Merkle-tree mode
+@node cm-hashed-shake-merkle
+@cindex cm-hashed-shake-merkle
+@subsection Hashed data with SHAKE in Merkle-tree mode
cSHAKE with either "LEAF" or "NODE" personalisation strings are used
instead of @code{0x00}/@code{0x01} constants prepending to the
@code{shake128-merkle}, @code{shake256-merkle} algorithm identifiers
are used.
-@node pki-hashed-skein512
-@subsection pki-hashed with Skein-512
+@node cm-hashed-skein512
+@cindex cm-hashed-skein512
+@subsection Hashed data with Skein-512
512-bit @url{https://www.schneier.com/academic/skein/, Skein-512} hash.
@code{skein512} algorithm identifier is used.
-@node pki-hashed-gost3411
-@subsection pki-hashed with GOST R 34.11-2012
+@node cm-hashed-gost3411
+@cindex cm-hashed-gost3411
+@subsection Hashed data with GOST R 34.11-2012
Streebog must be big-endian serialised.
@code{streebog256}, @code{streebog512} algorithm identifiers are used.
-@node pki-hashed-gost3411-merkle
-@subsection pki-hashed with GOST R 34.11-2012 in Merkle tree mode
+@node cm-hashed-gost3411-merkle
+@cindex cm-hashed-gost3411-merkle
+@subsection Hashed data with GOST R 34.11-2012 in Merkle tree mode
@code{streebog256-merkle}, @code{streebog512-merkle} algorithm
identifiers are used.
-@node pki-hashed-xxh3-128
-@subsection pki-hashed with XXH3-128
+@node cm-hashed-xxh3-128
+@cindex cm-hashed-xxh3-128
+@subsection Hashed data with XXH3-128
128-bit @url{https://xxhash.com/, XXH3} hash must be big-endian encoded.
They are written in
@url{https://datatracker.ietf.org/doc/html/rfc8610, CDDL}-like format.
-@include format/private-key.texi
+@include format/prv.texi
@include format/signed.texi
-@include format/cer.texi
+@include format/pub.texi
@include format/hashed.texi
@include format/encrypted.texi
@include format/registry.texi
ai = text ; algorithm identifier
av = {a: ai, v: bytes}
-private-key = av
+cm-prv = av
-@node private-key
-@cindex private-key
-@section private-key format
+@node cm-prv
+@cindex cm-prv
+@section cm-prv format
-@verbatiminclude format/private-key.cddl
+Private key container.
-Stored in a file, it should begin with "pki/prvkey" @ref{Magic, magic}.
+@verbatiminclude format/prv.cddl
-@node private-key-gost3410
-@subsection private-key with GOST R 34.10-2012
+Stored in a file, it should begin with "cm/prv" @ref{Magic, magic}.
+
+@node cm-prv-gost3410
+@cindex cm-prv-gost3410
+@subsection Private key with GOST R 34.10-2012
Big-endian private key representation must be used.
Following algorithm identifiers are used:
@code{gost3410-256A}, @code{gost3410-512C}.
-@node private-key-ed25519-blake2b
-@subsection private-key with Ed25519-BLAKE2b
+@node cm-prv-ed25519-blake2b
+@cindex cm-prv-ed25519-blake2b
+@subsection Private key with Ed25519-BLAKE2b
32-byte Ed25519 private key is used, as described in
@url{https://datatracker.ietf.org/doc/html/rfc8032, EdDSA} RFC.
@code{ed25519-blake2b} algorithm identifier is used, however actually no
hash is involved in private key storage.
-@node private-key-sntrup4591761-x25519
-@subsection private-key with SNTRUP4591761+X25519
+@node cm-prv-sntrup4591761-x25519
+@cindex cm-prv-sntrup4591761-x25519
+@subsection Private key with SNTRUP4591761+X25519
Concatenation of Streamlined NTRU Prime 4591^761's 1600-byte private key
and Curve25519's 32-byte one.
@code{sntrup4591761-x25519} algorithm identifier is used.
-@node private-key-mceliece6960119-x25519
-@subsection private-key with Classic McEliece 6960119+X25519
+@node cm-prv-mceliece6960119-x25519
+@cindex cm-prv-mceliece6960119-x25519
+@subsection Private key with Classic McEliece 6960119+X25519
Concatenation of Classic McEliece 6960119 13948-byte private key
and Curve25519's 32-byte one.
ai = text ; algorithm identifier
av = {a: ai, v: bytes}
-cer-load = {
+cm-pub-load = {
? ku: set,
pub: [+ {av, id: uuid}],
sub: {text => text}, ; subject
-cer-sig-tbs = {
+cm-pub-sig-tbs = {
sid: uuid, ; signer's public key id
- cid: uuid, ; certificate's id
+ cid: uuid, ; certification id
exp: validity,
* text => any
}
-@node cer
-@cindex cer
-@section cer format
+@node cm-pub
+@cindex cm-pub
+@section cm-pub format
-Certificate is the @code{@ref{pki-signed}} structure.
-Stored in a file, it should begin with "pki/cer" @ref{Magic, magic}.
+Public key is the @code{@ref{cm-signed}} structure.
+Stored in a file, it should begin with "cm/pub" @ref{Magic, magic}.
-Its @code{/load/t} equals to @code{cer}.
-@code{/load/v} contains @code{cer-load}:
+Its @code{/load/t} equals to @code{pub}.
+@code{/load/v} contains @code{cm-pub-load}:
@verbatim
-cer = pki-signed ; with /load/t = "cer", /load/v = cer-load
+cm-pub = cm-signed ; with /load/t = "pub", /load/v = cm-pub-load
@end verbatim
-@verbatiminclude format/cer-load.cddl
+@verbatiminclude format/pub-load.cddl
@table @code
and similar ones.
@item pub
-Certificate may contain multiple public keys.
+Public key container itself may contain multiple public keys.
That is @strong{solely} intended for tasks requiring more than single
key usage. For example @url{http://www.nncpgo.org, NNCP} uses one
curve25519 for (DH) encryption, one curve25519 for online authentication
and one ed25519 for signing purposes. All those three keys are used
-together. That certificate's key usage field must contain something like
+together. That public key's key usage field must contain something like
"nncp".
If your keypair is intended for general purposes like signing of
@item crit
Optional critical (in terms of X.509) extensions. Non-critical
-ones may be placed outside that map, directly in @code{cer-load}.
+ones may be placed outside that map, directly in @code{cm-pub-load}.
It @strong{must} be absent if empty. Values are extension specific.
@end table
-@code{pki-signed}'s @code{sig-tbs} @strong{must} contain additional fields:
+@code{cm-signed}'s @code{sig-tbs} @strong{must} contain additional fields:
-@verbatiminclude format/cer-sig-tbs.cddl
+@verbatiminclude format/pub-sig-tbs.cddl
@table @code
Signing public key identifier.
@item cid
-Certificate's unique identifier. UUIDv7 is a good choice. But it may be
+Certification unique identifier. UUIDv7 is a good choice. But it may be
UUIDv4, or any desired method of generation.
@item exp
-Expiration period of the certificate. It @strong{must} contain TAI64
+Certification expiration period. It @strong{must} contain TAI64
datetime (no nanoseconds).
@end table
-Example minimal certificate may look like:
+Example minimal public key may look like:
@verbatim
{
"load": {
- "t": "cer",
+ "t": "pub",
"v": {
"pub": [{"a": "gost3410-256A", "v": 'pubkey', "id": UUID(hash(pub))}],
"sub": {"CN": "Test", "O": "Testers"},
},
"sigs": [{
"tbs": {
- "cid": UUID(certificate's id),
+ "cid": UUID(certification id),
"sid": UUID(signer's pkid),
"exp": [TAI64, TAI64],
},
}
@end verbatim
-@node cer-gost3410
-@subsection cer with GOST R 34.10-2012
+@node cm-pub-gost3410
+@cindex cm-pub-gost3410
+@subsection Public key 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
Algorithm identifiers for the public key: @code{gost3410-256A},
@code{gost3410-512C}.
-Public key's identifier and @code{cid} should be calculated using
-big-endian Streebog-256 hash.
+Public key's identifier should be calculated using big-endian
+Streebog-256 hash.
-@node cer-ed25519-blake2b
-@subsection cer with Ed25519-BLAKE2b
+@node cm-pub-ed25519-blake2b
+@cindex cm-pub-ed25519-blake2b
+@subsection Public key with Ed25519-BLAKE2b
Same calculation and serialisation rules must be used as with
-@code{@ref{pki-signed-ed25519-blake2b}}.
-Public key's identifier and @code{cid} should be calculated
-using BLAKE2b hash with 128 or 256 bit output length specified.
-Algorithm identifiers for the public key: @code{ed25519ph-blake2b},
+@code{@ref{cm-signed-ed25519-blake2b}}.
-@node cer-sntrup4591761-x25519
-@subsection cer with SNTRUP4591761+X25519
+Public key's identifier should be calculated using BLAKE2b hash with 128
+or 256 bit output length specified.
-Certificate with combined Streamlined NTRU Prime 4591^761 and Curve25519
-public keys is used for KEM purposes, so should have "kem" key usage set.
+Algorithm identifier for the public key: @code{ed25519ph-blake2b}.
+
+@node cm-pub-sntrup4591761-x25519
+@cindex cm-pub-sntrup4591761-x25519
+@subsection Public key with SNTRUP4591761+X25519
+
+Combined Streamlined NTRU Prime 4591^761 and Curve25519 public keys are
+used for KEM purposes, so should have "kem" key usage set.
Its algorithm identifier is @code{sntrup4591761-x25519}. Its public key
value is a concatenation of 1218-byte SNTRUP4591761 public key and
32-byte Curve25519 one.
-Public key's identifier and @code{cid} should be calculated
-using BLAKE2b hash with 128 or 256 bit output length specified.
+Public key's identifier should be calculated using BLAKE2b hash with 128
+or 256 bit output length specified.
-@node cer-mceliece6960119-x25519
-@subsection cer with Classic McEliece 6960-119+x25519
+@node cm-pub-mceliece6960119-x25519
+@cindex cm-pub-mceliece6960119-x25519
+@subsection Public key with Classic McEliece 6960-119+x25519
-Certificate with combined Classic McEliece 6960-119 and Curve25519
-public keys is used for KEM purposes, so should have "kem" key usage set.
+Combined Classic McEliece 6960-119 and Curve25519 public keys are used
+for KEM purposes, so should have "kem" key usage set.
Its algorithm identifier is @code{mceliece6960119-x25519}. Its public key
value is a concatenation of 1047319-byte @code{mceliece6960119} public key
and 32-byte Curve25519 one.
-Public key's identifier and @code{cid} should be calculated
-using either SHAKE128 or SHAKE256 hash.
+Public key's identifier should be calculated using either SHAKE128 or
+SHAKE256 hash.
@table @code
@item blake2b, blake2b256
- @code{@ref{cer-ed25519-blake2b}},
- @code{@ref{pki-hashed-blake2b}},
- @code{@ref{pki-signed-ed25519-blake2b}}
+ @code{@ref{cm-pub-ed25519-blake2b}},
+ @code{@ref{cm-hashed-blake2b}},
+ @code{@ref{cm-signed-ed25519-blake2b}}
@item blake2b-merkle
- @code{@ref{pki-hashed-blake2b-merkle}},
- @code{@ref{pki-signed-ed25519-blake2b-merkle}}
+ @code{@ref{cm-hashed-blake2b-merkle}},
+ @code{@ref{cm-signed-ed25519-blake2b-merkle}}
@item blake3
- @code{@ref{pki-hashed-blake3}}
+ @code{@ref{cm-hashed-blake3}}
@item sha2-256, sha2-512
- @code{@ref{pki-hashed-sha2}}
+ @code{@ref{cm-hashed-sha2}}
@item shake128, shake256
- @code{@ref{pki-hashed-shake}}
+ @code{@ref{cm-hashed-shake}}
@item shake128-merkle, shake256-merkle
- @code{@ref{pki-hashed-shake-merkle}}
+ @code{@ref{cm-hashed-shake-merkle}}
@item skein512
- @code{@ref{pki-hashed-skein512}}
+ @code{@ref{cm-hashed-skein512}}
@item streebog256, streebog512
- @code{@ref{pki-hashed-gost3411}}
+ @code{@ref{cm-hashed-gost3411}}
@item streebog256-merkle, streebog512-merkle
- @code{@ref{pki-hashed-gost3411-merkle}}
+ @code{@ref{cm-hashed-gost3411-merkle}}
@item xxh3-128
- @code{@ref{pki-hashed-xxh3-128}}
+ @code{@ref{cm-hashed-xxh3-128}}
@end table
@node AI DH
@table @code
@item ecdsa-nist256p, ecdsa-nist521p
@item gost3410-256A, gost3410-512C
- @code{@ref{cer-gost3410}},
- @code{@ref{private-key-gost3410}}
+ @code{@ref{cm-pub-gost3410}},
+ @code{@ref{cm-prv-gost3410}}
@item x25519
@item x448
@end table
@table @code
@item chacha20poly1305
- @code{@ref{pki-encrypted-chacha20poly1305}}
+ @code{@ref{cm-encrypted-chacha20poly1305}}
@item kuznechik-ctracpkm-hmac-hkdf
- @code{@ref{pki-encrypted-kuznechik-ctracpkm-hmac-hkdf}}
+ @code{@ref{cm-encrypted-kuznechik-ctracpkm-hmac-hkdf}}
@end table
@node AI KEM
@table @code
@item argon2id-hkdf-blake2b
@item balloon-blake2b-hkdf
- @code{@ref{pki-encrypted-balloon-blake2b-hkdf}}
+ @code{@ref{cm-encrypted-balloon-blake2b-hkdf}}
@item gost3410-hkdf-kexp15
- @code{@ref{pki-encrypted-gost3410-hkdf-kexp15}}
+ @code{@ref{cm-encrypted-gost3410-hkdf-kexp15}}
@item mceliece6960119-x25519-hkdf-shake256
- @code{@ref{pki-encrypted-mceliece6960119-x25519-hkdf-shake256}}
+ @code{@ref{cm-encrypted-mceliece6960119-x25519-hkdf-shake256}}
@item mlkem768-x25519
@item sntrup761-x25519
@item sntrup4591761-x25519
- @code{@ref{cer-sntrup4591761-x25519}},
- @code{@ref{private-key-sntrup4591761-x25519}}
+ @code{@ref{cm-pub-sntrup4591761-x25519}},
+ @code{@ref{cm-prv-sntrup4591761-x25519}}
@item sntrup4591761-x25519-hkdf-blake2b
- @code{@ref{pki-encrypted-sntrup4591761-x25519-hkdf-blake2b}}
+ @code{@ref{cm-encrypted-sntrup4591761-x25519-hkdf-blake2b}}
@item sntrup761-x25519-hkdf-blake2b
@end table
@table @code
@item ecdsa-nist256p, ecdsa-nist521p
@item ed25519-blake2b
- @code{@ref{private-key-ed25519-blake2b}}
- @code{@ref{pki-signed-ed25519-blake2b}},
- @code{@ref{cer-ed25519-blake2b}}
+ @code{@ref{cm-prv-ed25519-blake2b}}
+ @code{@ref{cm-signed-ed25519-blake2b}},
+ @code{@ref{cm-pub-ed25519-blake2b}}
@item ed25519-blake2b-merkle
- @code{@ref{pki-signed-ed25519-blake2b-merkle}}
+ @code{@ref{cm-signed-ed25519-blake2b-merkle}}
@item ed448
@item gost3410-256A, gost3410-512C
- @code{@ref{cer-gost3410}},
- @code{@ref{private-key-gost3410}},
- @code{@ref{pki-signed-gost3410}}
+ @code{@ref{cm-pub-gost3410}},
+ @code{@ref{cm-prv-gost3410}},
+ @code{@ref{cm-signed-gost3410}}
@item gost3410-256A-merkle, gost3410-512C-merkle
- @code{@ref{pki-signed-gost3410-merkle}}
+ @code{@ref{cm-signed-gost3410-merkle}}
@end table
@node AI Content types
@subsection Content types
@itemize
-@item @ref{cer, @code{cer}}
-@item @ref{pki-signed, @code{data}}
-@item @ref{private-key, @code{prv}}
+@item @ref{cm-pub, @code{pub}}
+@item @ref{cm-signed, @code{data}}
+@item @ref{cm-prv, @code{prv}}
@end itemize
-pki-signed-prehash = {
+cm-signed-prehash = {
t: "prehash",
sigs: set, ; set of signature algorithm identifiers (/sigs/*/sign/a)
}
ai = text ; algorithm identifier
-pki-signed = {
+cm-signed = {
load: {
t: text,
? v: bytes / text / map / list,
},
sigs: [+ sig],
- ? certs: [+ cer],
+ ? pubs: [+ cm-pub],
}
sig = {
tbs: sig-tbs,
sign: {a: ai, v: bytes},
- ? cer-loc: [+ url],
+ ? pub-loc: [+ url],
* text => any
}
-@node pki-signed
-@cindex pki-signed
-@section pki-signed format
+@node cm-signed
+@cindex cm-signed
+@section cm-signed format
That resembles @url{https://datatracker.ietf.org/doc/html/rfc5652, CMS}
(PKCS#7) ASN.1-based format.
-Stored in a file, it should begin with "pki/signed" @ref{Magic, magic},
-unless it is a @ref{cer, certificate}.
+Stored in a file, it should begin with "cm/signed" @ref{Magic, magic},
+unless it is a @ref{cm-pub, public key}.
@verbatiminclude format/signed.cddl
@end verbatim
If no @code{/load/v} is provided, then the data is detached from the
-@code{pki-signed} structure itself and it is fed into hasher before that
+@code{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 @code{pki-signed}, you should use the
+detached data closely to the @code{cm-signed}, you should use the
following approach:
@verbatim
-pki-signed-prehash || BLOB(detached-data) || pki-signed
+cm-signed-prehash || BLOB(detached-data) || cm-signed
@end verbatim
@verbatiminclude format/signed-prehash.cddl
-With @code{pki-signed-prehash} you initialise your hashers used during
-signing process and fed BLOB's contents (not the encoded BLOB itself!)
+With @code{cm-signed-prehash} you initialise your hashers used during
+signing process and feed BLOB's contents (not the encoded BLOB itself!)
into the them.
@code{/sigs/*/tbs/when} is optional signing time.
placed in @code{/sigs/*/tbs} map. Non-protected (informational) fields
are placed outside it.
-@code{/certs} are optionally provided @ref{cer, certificates} to
+@code{/pubs} are optionally provided @ref{cm-pub, public keys} to
help creating the whole verification chain. They are placed outside
@code{/sigs}, because some of them may be shared among signers.
-If signed data is also intended to be @ref{pki-encrypted, encrypted},
+If signed data is also intended to be @ref{cm-encrypted, encrypted},
then @code{/sigs/*/tbs/encrypted-binding} should be set to
-@ref{pki-encrypted, encrypted}'s @code{/bind} value.
+@ref{cm-encrypted, encrypted}'s @code{/bind} value.
-@node pki-signed-gost3410
-@subsection pki-signed with GOST R 34.10-2012
+@node cm-signed-gost3410
+@cindex cm-signed-gost3410
+@subsection Signed data 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. Signature
Algorithm identifiers for the signature: @code{gost3410-256A},
@code{gost3410-512C}.
-@node pki-signed-gost3410-merkle
-@subsection pki-signed with GOST R 34.10-2012 with Merkle-tree hashing
+@node cm-signed-gost3410-merkle
+@cindex cm-signed-gost3410-merkle
+@subsection Signed data with GOST R 34.10-2012 with Merkle-tree hashing
- @ref{pki-hashed-gost3411-merkle} Merkle-tree hashing is used.
+ @ref{cm-hashed-gost3411-merkle} Merkle-tree hashing is used.
Algorithm identifiers for the signature: @code{gost3410-256A-merkle},
@code{gost3410-512C-merkle}.
-@node pki-signed-ed25519-blake2b
-@subsection pki-signed with Ed25519-BLAKE2b
+@node cm-signed-ed25519-blake2b
+@cindex cm-signed-ed25519-blake2b
+@subsection Signed data with Ed25519-BLAKE2b
@url{https://datatracker.ietf.org/doc/html/rfc8032, EdDSA} with
Edwards25519 is used similarly as in RFC 8032. But BLAKE2b is used
hash, using @code{ed25519ph-blake2b} algorithm identifier for
signature.
-@node pki-signed-ed25519-blake2b-merkle
-@subsection pki-signed with Ed25519-BLAKE2b with Merkle-tree hashing
+@node cm-signed-ed25519-blake2b-merkle
+@cindex cm-signed-ed25519-blake2b-merkle
+@subsection Signed data with Ed25519-BLAKE2b with Merkle-tree hashing
- @ref{pki-hashed-blake2b-merkle} Merkle-tree hashing is used.
+ @ref{cm-hashed-blake2b-merkle} Merkle-tree hashing is used.
HashEdDSA mode is used with @code{ed25519ph-blake2b-merkle}
algorithm identifier for signature.