| 267 | } |
| 268 | |
| 269 | func (c *Keychain) code(name string) string { |
| 270 | k, ok := c.keys[name] |
| 271 | if !ok { |
| 272 | log.Fatalf("no such key %q", name) |
| 273 | } |
| 274 | var code int |
| 275 | if k.offset != 0 { |
| 276 | n, err := strconv.ParseUint(string(c.data[k.offset:k.offset+counterLen]), 10, 64) |
| 277 | if err != nil { |
| 278 | log.Fatalf("malformed key counter for %q (%q)", name, c.data[k.offset:k.offset+counterLen]) |
| 279 | } |
| 280 | n++ |
| 281 | code = hotp(k.raw, n, k.digits) |
| 282 | f, err := os.OpenFile(c.file, os.O_RDWR, 0600) |
| 283 | if err != nil { |
| 284 | log.Fatalf("opening keychain: %v", err) |
| 285 | } |
| 286 | if _, err := f.WriteAt([]byte(fmt.Sprintf("%0*d", counterLen, n)), int64(k.offset)); err != nil { |
| 287 | log.Fatalf("updating keychain: %v", err) |
| 288 | } |
| 289 | if err := f.Close(); err != nil { |
| 290 | log.Fatalf("updating keychain: %v", err) |
| 291 | } |
| 292 | } else { |
| 293 | // Time-based key. |
| 294 | code = totp(k.raw, time.Now(), k.digits) |
| 295 | } |
| 296 | return fmt.Sprintf("%0*d", k.digits, code) |
| 297 | } |
| 298 | |
| 299 | func (c *Keychain) show(name string) { |
| 300 | code := c.code(name) |