66 lines
2.7 KiB
Go
66 lines
2.7 KiB
Go
package meshnodeenrollerclient
|
|
|
|
import (
|
|
"crypto/sha256"
|
|
"encoding/base64"
|
|
"encoding/hex"
|
|
"encoding/json"
|
|
"strings"
|
|
)
|
|
|
|
// **Redeem** (§6): what a joining node-engine sends, and what the holder answers. Shared by the holder and the engine,
|
|
// which live in two repositories.
|
|
|
|
// Redeem is the redeem verb's call: the node, the public halves of its keys and its identity key's signature over
|
|
// RedeemProof. No token: the bus's login check verified it.
|
|
type Redeem struct {
|
|
Node string `json:"node"`
|
|
PublicKey string `json:"public_key"`
|
|
OverlayKey string `json:"overlay_key,omitempty"`
|
|
SealingKey string `json:"sealing_key"`
|
|
ServingKey string `json:"serving_key,omitempty"`
|
|
Profile map[string]any `json:"profile,omitempty"`
|
|
Tunnel json.RawMessage `json:"tunnel,omitempty"`
|
|
Proof string `json:"proof"`
|
|
}
|
|
|
|
// RedeemProof is the bytes a node signs with its identity key when it redeems: its name and every public key it
|
|
// presents, so a proof cannot be moved to another node or other keys. The holder builds the same bytes.
|
|
func RedeemProof(node, public, overlay, sealing, serving string) []byte {
|
|
return []byte("novox-mesh-redeem v1\x00" + node + "\x00" + public + "\x00" + overlay + "\x00" + sealing + "\x00" + serving)
|
|
}
|
|
|
|
// KeysDigest is the digest of the public keys a redeem presents, `sha256:<hex>`: what the key at redeeming and the
|
|
// events carry, the one hash an event carries (§1).
|
|
func KeysDigest(public, overlay, sealing, serving string) string {
|
|
sum := sha256.Sum256([]byte(strings.Join([]string{public, overlay, sealing, serving}, "\x00")))
|
|
return "sha256:" + hex.EncodeToString(sum[:])
|
|
}
|
|
|
|
// KeysDigest is r's keys' digest.
|
|
func (r Redeem) KeysDigest() string {
|
|
return KeysDigest(r.PublicKey, r.OverlayKey, r.SealingKey, r.ServingKey)
|
|
}
|
|
|
|
// ProofBytes is r's proof decoded from base64.
|
|
func (r Redeem) ProofBytes() ([]byte, error) { return base64.StdEncoding.DecodeString(r.Proof) }
|
|
|
|
// RedeemAnswer is what redeem answers (§6): the node, the login it dials as next, its account sealed to the sealing key it
|
|
// presented (base64), its certificate as PEM, the vault's public signing half (base64), and the vault's signature over
|
|
// SignedBytes under the context of KindEnrolment. The engine refuses an answer not signed by the key its token carries.
|
|
type RedeemAnswer struct {
|
|
Node string `json:"node"`
|
|
Login string `json:"login"`
|
|
Account string `json:"account"`
|
|
Certificate string `json:"certificate"`
|
|
Signer string `json:"signer"`
|
|
Signature string `json:"signature,omitempty"`
|
|
}
|
|
|
|
// SignedBytes is what the vault signs of a: a without its signature, as JSON.
|
|
func (a RedeemAnswer) SignedBytes() []byte {
|
|
a.Signature = ""
|
|
raw, _ := json.Marshal(a)
|
|
return raw
|
|
}
|