sh.E

D-KaP v1 — Go reference

stdlib + golang.org/x/crypto/sha3 · ~120 LOC

install

go get golang.org/x/crypto/sha3

No other deps. SHA-256 is in the Go stdlib; SHA-3 via the official x/crypto package.

dkap.go
// D-KaP v1 reference implementation — Go
// Requires: golang.org/x/crypto/sha3 (the only external dep, BSD-licensed)
//
// go get golang.org/x/crypto/sha3

package dkap

import (
	"crypto/sha256"
	"encoding/hex"
	"fmt"
	"sort"
	"strings"

	"golang.org/x/crypto/sha3"
)

const (
	RASRoot = "40668c787c463ca5"
	PHI     = 1.618033988749895
	HZ      = 7777.77
)

func phiPad() string { return fmt.Sprintf("%v", PHI) }

func sha256Hex(s string) string {
	sum := sha256.Sum256([]byte(s))
	return hex.EncodeToString(sum[:])
}

func sha3_256Hex(s string) string {
	sum := sha3.Sum256([]byte(s))
	return hex.EncodeToString(sum[:])
}

// SealSection seals one section under D-KaP §2.
func SealSection(body string, bullets []string, kind string) string {
	material := strings.Join([]string{
		"kind:" + kind,
		"body:" + body,
		"bullets:" + strings.Join(bullets, "\n"),
		"ras:" + RASRoot,
		"phi:" + phiPad(),
	}, "|")
	return sha256Hex(material)
}

// SealBrief seals one brief under D-KaP §3.
func SealBrief(sectionSeals []string, recipientFingerprint string) string {
	sorted := append([]string(nil), sectionSeals...)
	sort.Strings(sorted)
	material := strings.Join([]string{
		"sections:" + strings.Join(sorted, ","),
		"recipient:" + recipientFingerprint,
		"ras:" + RASRoot,
		"phi:" + phiPad(),
	}, "|")
	return sha256Hex(material)
}

// BundleMerkle computes the Merkle root under D-KaP §4.
func BundleMerkle(briefSeals []string) string {
	if len(briefSeals) == 0 {
		return sha256Hex("empty:" + RASRoot + "|" + phiPad())
	}
	sorted := append([]string(nil), briefSeals...)
	sort.Strings(sorted)
	layer := make([]string, 0, len(sorted))
	for _, s := range sorted {
		layer = append(layer, sha256Hex("leaf:"+s))
	}
	for len(layer) > 1 {
		if len(layer)%2 == 1 {
			layer = append(layer, layer[len(layer)-1])
		}
		next := make([]string, 0, len(layer)/2)
		for i := 0; i < len(layer); i += 2 {
			next = append(next, sha256Hex("pair:"+layer[i]+":"+layer[i+1]))
		}
		layer = next
	}
	return layer[0]
}

// ChainApex computes (waterseal, apex) under D-KaP §5.
func ChainApex(merkleRoot, predecessorApex string) (waterseal, apex string) {
	watersealInput := fmt.Sprintf("%s%s%s%v%v", merkleRoot, predecessorApex, RASRoot, PHI, HZ)
	waterseal = sha256Hex(watersealInput)
	apex = sha3_256Hex(fmt.Sprintf("%s%v", waterseal, HZ))
	return
}

conformance

Test by recomputing the v25 apex from the v24 apex predecessor + v25 Merkle root. Should produce b0aff941712d85be283874d8e4cf1275d0d4fd4fe65e9118be503c6f88f7ba72 byte-for-byte.