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.
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.
// 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
}
Test by recomputing the v25 apex from the v24 apex predecessor + v25 Merkle root. Should produce
b0aff941712d85be283874d8e4cf1275d0d4fd4fe65e9118be503c6f88f7ba72 byte-for-byte.