age

Simple, secure encryption with UNIX-style composability.
git clone git://git.sgregoratto.me/age
Log | Files | Refs | README | LICENSE

parse.go (1931B)


      1 // Copyright 2019 Google LLC
      2 //
      3 // Use of this source code is governed by a BSD-style
      4 // license that can be found in the LICENSE file or at
      5 // https://developers.google.com/open-source/licenses/bsd
      6 
      7 package main
      8 
      9 import (
     10 	"bufio"
     11 	"fmt"
     12 	"io"
     13 	"io/ioutil"
     14 	"os"
     15 	"strings"
     16 
     17 	"github.com/FiloSottile/age/internal/age"
     18 )
     19 
     20 func parseRecipient(arg string) (age.Recipient, error) {
     21 	switch {
     22 	case strings.HasPrefix(arg, "pubkey:"):
     23 		return age.ParseX25519Recipient(arg)
     24 	case strings.HasPrefix(arg, "ssh-"):
     25 		return age.ParseSSHRecipient(arg)
     26 	}
     27 
     28 	return nil, fmt.Errorf("unknown recipient type: %q", arg)
     29 }
     30 
     31 func parseIdentitiesFile(name string) ([]age.Identity, error) {
     32 	f, err := os.Open(name)
     33 	if err != nil {
     34 		return nil, fmt.Errorf("failed to open file: %v", err)
     35 	}
     36 
     37 	var ids []age.Identity
     38 	scanner := bufio.NewScanner(f)
     39 	for scanner.Scan() {
     40 		line := scanner.Text()
     41 		if strings.HasPrefix(line, "#") || line == "" {
     42 			continue
     43 		}
     44 		i, err := age.ParseX25519Identity(line)
     45 		if err != nil {
     46 			return nil, fmt.Errorf("malformed secret keys file %q: %v", name, err)
     47 		}
     48 		ids = append(ids, i)
     49 	}
     50 	if err := scanner.Err(); err != nil {
     51 		return nil, fmt.Errorf("failed to read %q: %v", name, err)
     52 	}
     53 
     54 	if len(ids) == 0 {
     55 		return nil, fmt.Errorf("no secret keys found in %q", name)
     56 	}
     57 	return ids, nil
     58 }
     59 
     60 func parseSSHIdentity(name string) ([]age.Identity, error) {
     61 	f, err := os.Open(name)
     62 	if err != nil {
     63 		return nil, fmt.Errorf("failed to open file: %v", err)
     64 	}
     65 	defer f.Close()
     66 
     67 	// Don't allow unbounded reads.
     68 	// TODO: support for multiple keys in the same stream, such as user.keys
     69 	// on GitHub.
     70 	pemBytes, err := ioutil.ReadAll(io.LimitReader(f, 1<<20))
     71 	if err != nil {
     72 		return nil, fmt.Errorf("failed to read %q: %v", name, err)
     73 	}
     74 
     75 	id, err := age.ParseSSHIdentity(pemBytes)
     76 	if err != nil {
     77 		return nil, fmt.Errorf("malformed SSH identity in %q: %v", name, err)
     78 	}
     79 
     80 	return []age.Identity{id}, nil
     81 }