| 81 | } |
| 82 | |
| 83 | func (ca *ClientAuth) Parse(authKey string) error { |
| 84 | if len(authKey) == 0 { |
| 85 | return errors.New("auth key should not be empty") |
| 86 | } |
| 87 | |
| 88 | decr := bytes.NewReader(base58.Decode(authKey)) |
| 89 | |
| 90 | ver, err := decr.ReadByte() |
| 91 | if err != nil { |
| 92 | return errors.New("read authkey version") |
| 93 | } |
| 94 | |
| 95 | if ver != 1 { |
| 96 | return fmt.Errorf("unsupported authkey version %q", ver) |
| 97 | } |
| 98 | |
| 99 | typ, err := decr.ReadByte() |
| 100 | if err != nil { |
| 101 | return errors.New("read authkey peer type") |
| 102 | } |
| 103 | |
| 104 | if typ == 1 { |
| 105 | ca.Web = true |
| 106 | } |
| 107 | |
| 108 | ipLenB, err := decr.ReadByte() |
| 109 | if err != nil { |
| 110 | return errors.New("read STUN ip len; invalid authkey") |
| 111 | } |
| 112 | |
| 113 | ipLen := int(ipLenB) |
| 114 | if ipLen > 0 { |
| 115 | stunIPBytes := make([]byte, ipLen+2) |
| 116 | n, err := decr.Read(stunIPBytes) |
| 117 | if n != len(stunIPBytes) || err != nil { |
| 118 | return errors.New("read STUN ip; invalid authkey") |
| 119 | } |
| 120 | |
| 121 | err = ca.ReceiverStunAddr.UnmarshalBinary(stunIPBytes) |
| 122 | if err != nil { |
| 123 | return fmt.Errorf("unmarshal receiver stun address: %w", err) |
| 124 | } |
| 125 | } |
| 126 | |
| 127 | derpRegionBytes := make([]byte, 2) |
| 128 | n, err := decr.Read(derpRegionBytes) |
| 129 | if n != len(derpRegionBytes) || err != nil { |
| 130 | return errors.New("read derp region; invalid authkey") |
| 131 | } |
| 132 | ca.ReceiverDERPRegionID = binary.BigEndian.Uint16(derpRegionBytes) |
| 133 | |
| 134 | pubKeyBytes := make([]byte, 32) |
| 135 | n, err = decr.Read(pubKeyBytes) |
| 136 | if n != len(pubKeyBytes) || err != nil { |
| 137 | return errors.New("read receiver pubkey; invalid authkey") |
| 138 | } |
| 139 | ca.ReceiverPublicKey = key.NodePublicFromRaw32(mem.B(pubKeyBytes)) |
| 140 | |