forked from gopasspw/gopass
-
-
Notifications
You must be signed in to change notification settings - Fork 0
/
secret.go
153 lines (124 loc) · 2.77 KB
/
secret.go
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
140
141
142
143
144
145
146
147
148
149
150
151
152
153
package secret
import (
"bytes"
"os"
"reflect"
"strings"
"sync"
"github.com/justwatchcom/gopass/pkg/store"
)
var debug bool
func init() {
if gdb := os.Getenv("GOPASS_DEBUG"); gdb != "" {
debug = true
}
}
// Secret is a decoded secret
type Secret struct {
sync.Mutex
password string
body string
data map[string]interface{}
}
// New creates a new secret
func New(password, body string) *Secret {
return &Secret{
password: password,
body: body,
}
}
// Parse decodes an secret. It will always return a valid secret. If decoding
// the body to YAML is may return an error which can be ignored.
func Parse(buf []byte) (*Secret, error) {
s := &Secret{}
lines := bytes.SplitN(buf, []byte("\n"), 2)
if len(lines) > 0 {
s.password = string(bytes.TrimSpace(lines[0]))
}
if len(lines) > 1 {
s.body = string(bytes.TrimSpace(lines[1]))
}
if err := s.decode(); err != nil {
return s, err
}
return s, nil
}
// Bytes encodes an secret
func (s *Secret) Bytes() ([]byte, error) {
buf := &bytes.Buffer{}
_, _ = buf.WriteString(s.password)
if s.body != "" {
_, _ = buf.WriteString("\n")
_, _ = buf.WriteString(s.body)
}
return buf.Bytes(), nil
}
// String encodes and returns a string representation of a secret
func (s *Secret) String() string {
var buf strings.Builder
_, _ = buf.WriteString(s.password)
if s.body != "" {
_, _ = buf.WriteString("\n")
_, _ = buf.WriteString(s.body)
}
return buf.String()
}
// Password returns the first line from a secret
func (s *Secret) Password() string {
s.Lock()
defer s.Unlock()
return s.password
}
// SetPassword sets a new password (i.e. the first line)
func (s *Secret) SetPassword(pw string) {
s.Lock()
defer s.Unlock()
s.password = pw
}
// Body returns the body of a secret. If the body was valid YAML it returns an
// empty string
func (s *Secret) Body() string {
s.Lock()
defer s.Unlock()
return s.body
}
// Data returns the data of a secret. Unless the body was valid YAML, it returns
// an map
func (s *Secret) Data() map[string]interface{} {
s.Lock()
defer s.Unlock()
return s.data
}
// SetBody sets a new body possibly erasing an decoded YAML map
func (s *Secret) SetBody(b string) error {
s.Lock()
defer s.Unlock()
s.body = b
s.data = nil
err := s.decode()
return err
}
// Equal returns true if two secrets are equal
func (s *Secret) Equal(other store.Secret) bool {
if s == nil && (other == nil || reflect.ValueOf(other).IsNil()) {
return true
}
if s == nil || other == nil || reflect.ValueOf(other).IsNil() {
return false
}
s.Lock()
defer s.Unlock()
if s.password != other.Password() {
return false
}
if s.body != other.Body() {
return false
}
return true
}
func (s *Secret) encode() error {
return s.encodeKV()
}
func (s *Secret) decode() error {
return s.decodeKV()
}