package util import ( "encoding/json" "errors" "regexp" "strings" "tailscale.com/types/key" ) const ( // These constants are copied from the upstream tailscale.com/types/key // library, because they are not exported. // https://github.com/tailscale/tailscale/tree/main/types/key // nodePublicHexPrefix is the prefix used to identify a // hex-encoded node public key. // // This prefix is used in the control protocol, so cannot be // changed. nodePublicHexPrefix = "nodekey:" // machinePublicHexPrefix is the prefix used to identify a // hex-encoded machine public key. // // This prefix is used in the control protocol, so cannot be // changed. machinePublicHexPrefix = "mkey:" // discoPublicHexPrefix is the prefix used to identify a // hex-encoded disco public key. // // This prefix is used in the control protocol, so cannot be // changed. discoPublicHexPrefix = "discokey:" // privateKey prefix. privateHexPrefix = "privkey:" PermissionFallback = 0o700 ZstdCompression = "zstd" ) var ( NodePublicKeyRegex = regexp.MustCompile("nodekey:[a-fA-F0-9]+") ErrCannotDecryptResponse = errors.New("cannot decrypt response") ) func MachinePublicKeyStripPrefix(machineKey key.MachinePublic) string { return strings.TrimPrefix(machineKey.String(), machinePublicHexPrefix) } func NodePublicKeyStripPrefix(nodeKey key.NodePublic) string { return strings.TrimPrefix(nodeKey.String(), nodePublicHexPrefix) } func DiscoPublicKeyStripPrefix(discoKey key.DiscoPublic) string { return strings.TrimPrefix(discoKey.String(), discoPublicHexPrefix) } func MachinePublicKeyEnsurePrefix(machineKey string) string { if !strings.HasPrefix(machineKey, machinePublicHexPrefix) { return machinePublicHexPrefix + machineKey } return machineKey } func NodePublicKeyEnsurePrefix(nodeKey string) string { if !strings.HasPrefix(nodeKey, nodePublicHexPrefix) { return nodePublicHexPrefix + nodeKey } return nodeKey } func DiscoPublicKeyEnsurePrefix(discoKey string) string { if !strings.HasPrefix(discoKey, discoPublicHexPrefix) { return discoPublicHexPrefix + discoKey } return discoKey } func PrivateKeyEnsurePrefix(privateKey string) string { if !strings.HasPrefix(privateKey, privateHexPrefix) { return privateHexPrefix + privateKey } return privateKey } func DecodeAndUnmarshalNaCl( msg []byte, output interface{}, pubKey *key.MachinePublic, privKey *key.MachinePrivate, ) error { // log.Trace(). // Str("pubkey", pubKey.ShortString()). // Int("length", len(msg)). // Msg("Trying to decrypt") decrypted, ok := privKey.OpenFrom(*pubKey, msg) if !ok { return ErrCannotDecryptResponse } if err := json.Unmarshal(decrypted, output); err != nil { return err } return nil }