summaryrefslogtreecommitdiffhomepage
path: root/cmd
diff options
context:
space:
mode:
Diffstat (limited to 'cmd')
-rw-r--r--cmd/nodekey/nodekey.go85
1 files changed, 85 insertions, 0 deletions
diff --git a/cmd/nodekey/nodekey.go b/cmd/nodekey/nodekey.go
new file mode 100644
index 000000000..97ff6cbcf
--- /dev/null
+++ b/cmd/nodekey/nodekey.go
@@ -0,0 +1,85 @@
+package main
+
+import (
+ "fmt"
+ "log"
+ "os"
+
+ "go4.org/mem"
+ "tailscale.com/types/key"
+)
+
+func main() {
+ for _, arg := range os.Args[1:] {
+ k, err := key.ParseNodePublicUntyped(mem.B([]byte(arg)))
+ if err != nil {
+ log.Printf("invalid node key %q: %v", arg, err)
+ }
+ b, err := parseDebug32(arg)
+ if err != nil {
+ log.Printf("invalid debug32 format for %q: %v", arg, err)
+ }
+ k = key.NodePublicFromRaw32(mem.B(b[:]))
+ log.Printf("node key: %s", k.ShortString())
+ log.Printf("node key: %s", k.String())
+ }
+}
+
+// parseDebug32 attempts to reconstruct the first 4 bytes of a key
+// from the Tailscale debug representation like "[abcde]".
+// The remaining bytes will be zero.
+func parseDebug32(s string) ([32]byte, error) {
+ var k [32]byte
+
+ if s == "" {
+ return k, nil
+ }
+ if len(s) != 7 || s[0] != '[' || s[6] != ']' {
+ return k, fmt.Errorf("invalid debug32 format %q", s)
+ }
+
+ decode64 := func(c byte) (byte, bool) {
+ switch {
+ case 'A' <= c && c <= 'Z':
+ return c - 'A', true
+ case 'a' <= c && c <= 'z':
+ return c - 'a' + 26, true
+ case '0' <= c && c <= '9':
+ return c - '0' + 52, true
+ case c == '+':
+ return 62, true
+ case c == '/':
+ return 63, true
+ default:
+ return 0, false
+ }
+ }
+
+ v0, ok := decode64(s[1])
+ if !ok {
+ return k, fmt.Errorf("invalid debug32 format %q", s)
+ }
+ v1, ok := decode64(s[2])
+ if !ok {
+ return k, fmt.Errorf("invalid debug32 format %q", s)
+ }
+ v2, ok := decode64(s[3])
+ if !ok {
+ return k, fmt.Errorf("invalid debug32 format %q", s)
+ }
+ v3, ok := decode64(s[4])
+ if !ok {
+ return k, fmt.Errorf("invalid debug32 format %q", s)
+ }
+ v4, ok := decode64(s[5])
+ if !ok {
+ return k, fmt.Errorf("invalid debug32 format %q", s)
+ }
+
+ k[0] = v0<<2 | v1>>4
+ k[1] = v1<<4 | v2>>2
+ k[2] = v2<<6 | v3
+ k[3] = v4 << 2 // low 2 bits were discarded by debug32
+
+ return k, nil
+}