| 154 | const counterLen = 20 |
| 155 | |
| 156 | func readKeychain(file string) *Keychain { |
| 157 | c := &Keychain{ |
| 158 | file: file, |
| 159 | keys: make(map[string]Key), |
| 160 | } |
| 161 | data, err := ioutil.ReadFile(file) |
| 162 | if err != nil { |
| 163 | if os.IsNotExist(err) { |
| 164 | return c |
| 165 | } |
| 166 | log.Fatal(err) |
| 167 | } |
| 168 | c.data = data |
| 169 | |
| 170 | lines := bytes.SplitAfter(data, []byte("\n")) |
| 171 | offset := 0 |
| 172 | for i, line := range lines { |
| 173 | lineno := i + 1 |
| 174 | offset += len(line) |
| 175 | f := bytes.Split(bytes.TrimSuffix(line, []byte("\n")), []byte(" ")) |
| 176 | if len(f) == 1 && len(f[0]) == 0 { |
| 177 | continue |
| 178 | } |
| 179 | if len(f) >= 3 && len(f[1]) == 1 && '6' <= f[1][0] && f[1][0] <= '8' { |
| 180 | var k Key |
| 181 | name := string(f[0]) |
| 182 | k.digits = int(f[1][0] - '0') |
| 183 | raw, err := decodeKey(string(f[2])) |
| 184 | if err == nil { |
| 185 | k.raw = raw |
| 186 | if len(f) == 3 { |
| 187 | c.keys[name] = k |
| 188 | continue |
| 189 | } |
| 190 | if len(f) == 4 && len(f[3]) == counterLen { |
| 191 | _, err := strconv.ParseUint(string(f[3]), 10, 64) |
| 192 | if err == nil { |
| 193 | // Valid counter. |
| 194 | k.offset = offset - counterLen |
| 195 | if line[len(line)-1] == '\n' { |
| 196 | k.offset-- |
| 197 | } |
| 198 | c.keys[name] = k |
| 199 | continue |
| 200 | } |
| 201 | } |
| 202 | } |
| 203 | } |
| 204 | log.Printf("%s:%d: malformed key", c.file, lineno) |
| 205 | } |
| 206 | return c |
| 207 | } |
| 208 | |
| 209 | func (c *Keychain) list() { |
| 210 | var names []string |