File: base64.go

package info (click to toggle)
golang-github-smallstep-cli 0.15.16%2Bds-3
  • links: PTS, VCS
  • area: main
  • in suites: bookworm
  • size: 4,404 kB
  • sloc: sh: 512; makefile: 99
file content (139 lines) | stat: -rw-r--r-- 3,104 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
package base64

import (
	"bytes"
	"encoding/base64"
	"fmt"
	"os"
	"strings"

	"github.com/pkg/errors"
	"github.com/smallstep/cli/command"
	"github.com/smallstep/cli/utils"
	"github.com/urfave/cli"
)

func init() {
	cmd := cli.Command{
		Name:   "base64",
		Action: command.ActionFunc(base64Action),
		Usage:  "encodes and decodes using base64 representation",
		UsageText: `**step base64**
[**-d**|**--decode**] [**-r**|**--raw**] [**-u**|**--url**]`,
		Description: `**step base64** implements base64 encoding as specified by RFC 4648.

## Examples

Encode to base64 using the standard encoding:
'''
$ echo -n This is the string to encode | step base64
VGhpcyBpcyB0aGUgc3RyaW5nIHRvIGVuY29kZQ==
$ step base64 This is the string to encode 
VGhpcyBpcyB0aGUgc3RyaW5nIHRvIGVuY29kZQ==
'''

Decode a base64 encoded string:
'''
$ echo VGhpcyBpcyB0aGUgc3RyaW5nIHRvIGVuY29kZQ== | step base64 -d
This is the string to encode
'''

Encode to base64 without padding:
'''
$ echo -n This is the string to encode | step base64 -r
VGhpcyBpcyB0aGUgc3RyaW5nIHRvIGVuY29kZQ
$ step base64 -r This is the string to encode
VGhpcyBpcyB0aGUgc3RyaW5nIHRvIGVuY29kZQ
'''

Encode to base64 using the url encoding:
'''
$ echo 'abc123$%^&*()_+-=~' | step base64 -u
YWJjMTIzJCVeJiooKV8rLT1-Cg==
'''

Decode an url encoded base64 string. The encoding type can be enforced
using the '-u' or '-r' flags, but it will be autodetected if they are not
passed:
'''
$ echo YWJjMTIzJCVeJiooKV8rLT1-Cg== | step base64 -d
abc123$%^&*()_+-=~
$ echo YWJjMTIzJCVeJiooKV8rLT1-Cg== | step base64 -d -u
abc123$%^&*()_+-=~
'''`,
		Flags: []cli.Flag{
			cli.BoolFlag{
				Name:  "d,decode",
				Usage: "decode base64 input",
			},
			cli.BoolFlag{
				Name:  "r,raw",
				Usage: "use the unpadded base64 encoding",
			},
			cli.BoolFlag{
				Name:  "u,url",
				Usage: "use the encoding format typically used in URLs and file names",
			},
		},
	}

	command.Register(cmd)
}

func base64Action(ctx *cli.Context) error {
	var err error
	var data []byte
	isDecode := ctx.Bool("decode")

	if ctx.NArg() > 0 {
		data = []byte(strings.Join(ctx.Args(), " "))
	} else {
		var prompt string
		if isDecode {
			prompt = "Please enter text to decode"
		} else {
			prompt = "Please enter text to encode"
		}

		if data, err = utils.ReadInput(prompt); err != nil {
			return err
		}
	}

	enc := getEncoder(ctx, data)
	if isDecode {
		b, err := enc.DecodeString(string(data))
		if err != nil {
			return errors.Wrap(err, "error decoding input")
		}
		os.Stdout.Write(b)
	} else {
		fmt.Println(enc.EncodeToString(data))
	}

	return nil
}

func getEncoder(ctx *cli.Context, data []byte) *base64.Encoding {
	raw := ctx.Bool("raw")
	url := ctx.Bool("url")
	isDecode := ctx.Bool("decode")

	// Detect encoding
	if isDecode && !ctx.IsSet("raw") && !ctx.IsSet("url") {
		raw = !bytes.HasSuffix(bytes.TrimSpace(data), []byte("="))
		url = bytes.Contains(data, []byte("-")) || bytes.Contains(data, []byte("_"))
	}

	if raw {
		if url {
			return base64.RawURLEncoding
		}
		return base64.RawStdEncoding
	}
	if url {
		return base64.URLEncoding
	}

	return base64.StdEncoding
}