Skip to content

Commit 98ec488

Browse files
authored
add protonpass *.zip support (#43)
1 parent 12507be commit 98ec488

File tree

5 files changed

+49
-3
lines changed

5 files changed

+49
-3
lines changed

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ andcli can handle input from the following providers (if they provide more than
1111
- [2fas](https://2fas.com)
1212
- [Stratum / Authenticator Pro](https://stratumauth.com)
1313
- [Keepass](https://www.keepassdx.com/) or anything else that exports \*.kdbx v2
14-
- [ProtonPass](https://proton.me/pass)
14+
- [ProtonPass](https://proton.me/pass) in \*.pgp and \*.zip format
1515

1616
At the moment only TOTP entries are supported.
1717

internal/vaults/protonpass/protonpass.go

Lines changed: 45 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,12 @@
11
package protonpass
22

33
import (
4+
"archive/zip"
5+
"bytes"
46
"encoding/json"
7+
"errors"
58
"fmt"
9+
"io"
610
"log"
711
"net/url"
812
"os"
@@ -36,7 +40,7 @@ type (
3640

3741
func Open(filename string, pass []byte) (vaults.Vault, error) {
3842

39-
b, err := os.ReadFile(filename)
43+
b, err := read(filename)
4044
if err != nil {
4145
return nil, fmt.Errorf("%s: %s", t, err)
4246
}
@@ -97,3 +101,43 @@ func (e envelope) Entries() []vaults.Entry {
97101

98102
return entries
99103
}
104+
105+
// opens, reads and returns file content, handles zip if necessary.
106+
func read(filename string) ([]byte, error) {
107+
108+
sig := []byte{0x50, 0x4b, 0x03, 0x04}
109+
110+
f, err := os.Open(filename)
111+
if err != nil {
112+
return nil, err
113+
}
114+
defer f.Close()
115+
116+
head := make([]byte, 4)
117+
if _, err := f.ReadAt(head, 0); err != nil {
118+
return nil, err
119+
}
120+
121+
// not a zip file
122+
if !bytes.Equal(head, sig) {
123+
return os.ReadFile(filename)
124+
}
125+
126+
r, err := zip.OpenReader(filename)
127+
if err != nil {
128+
return nil, err
129+
}
130+
131+
if len(r.File) == 0 {
132+
return nil, errors.New("archive has no content")
133+
}
134+
135+
// read only the first entry.
136+
rc, err := r.File[0].Open()
137+
if err != nil {
138+
return nil, err
139+
}
140+
defer rc.Close()
141+
142+
return io.ReadAll(rc)
143+
}

internal/vaults/protonpass/protonpass_test.go

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,9 @@ func TestOpen(t *testing.T) {
1616
password string
1717
fails bool
1818
}{
19-
{"decrypts", "testdata/protonpass-test.pgp", "andcli-test", false},
19+
{"decrypts text", "testdata/protonpass-test.pgp", "andcli-test", false},
20+
{"decrypts zip", "testdata/protonpass-test.pgp.zip", "andcli-test", false},
21+
{"decrypts hidden zip", "testdata/protonpass-test.pgp.data", "andcli-test", false},
2022
{"fails: wrong password", "testdata/protonpass-test.pgp", "", true},
2123
}
2224

3.35 KB
Binary file not shown.
3.35 KB
Binary file not shown.

0 commit comments

Comments
 (0)