mirror of
https://github.com/moonD4rk/HackBrowserData.git
synced 2026-07-04 21:37:47 +02:00
Merge pull request #159 from moonD4rk/dev
refactor: formatting code used to pass golangci-lint rules
This commit is contained in:
@@ -0,0 +1,69 @@
|
|||||||
|
run:
|
||||||
|
timeout: '5m'
|
||||||
|
skip-dirs:
|
||||||
|
- 'assets'
|
||||||
|
allow-parallel-runners: true
|
||||||
|
modules-download-mode: 'readonly'
|
||||||
|
|
||||||
|
linters:
|
||||||
|
enable:
|
||||||
|
- 'asciicheck'
|
||||||
|
- 'deadcode'
|
||||||
|
- 'depguard'
|
||||||
|
- 'dogsled'
|
||||||
|
- 'errorlint'
|
||||||
|
- 'exportloopref'
|
||||||
|
- 'gofmt'
|
||||||
|
- 'goheader'
|
||||||
|
- 'goimports'
|
||||||
|
- 'gomodguard'
|
||||||
|
- 'goprintffuncname'
|
||||||
|
- 'gosec'
|
||||||
|
- 'govet'
|
||||||
|
- 'ineffassign'
|
||||||
|
- 'makezero'
|
||||||
|
- 'misspell'
|
||||||
|
- 'paralleltest'
|
||||||
|
- 'prealloc'
|
||||||
|
- 'predeclared'
|
||||||
|
- 'revive'
|
||||||
|
- 'typecheck'
|
||||||
|
- 'unconvert'
|
||||||
|
- 'varcheck'
|
||||||
|
- 'whitespace'
|
||||||
|
disable:
|
||||||
|
# unsupported lint with golang 1.18+ ref: https://github.com/golangci/golangci-lint/issues/2649
|
||||||
|
- 'bodyclose'
|
||||||
|
- 'gosimple'
|
||||||
|
- 'noctx'
|
||||||
|
- 'sqlclosecheck'
|
||||||
|
- 'staticcheck'
|
||||||
|
- 'structcheck'
|
||||||
|
- 'stylecheck'
|
||||||
|
- 'unused'
|
||||||
|
- 'errcheck'
|
||||||
|
|
||||||
|
issues:
|
||||||
|
exclude-use-default: false
|
||||||
|
exclude:
|
||||||
|
- should have a package comment
|
||||||
|
- should have comment
|
||||||
|
# G101: Potential hardcoded credentials
|
||||||
|
- G101
|
||||||
|
# G103: Use of unsafe calls should be audited
|
||||||
|
- G103
|
||||||
|
# G304: Potential file inclusion via variable
|
||||||
|
- G304
|
||||||
|
# G404, G401, G502, G505: weak cryptographic list
|
||||||
|
- G401
|
||||||
|
- G404
|
||||||
|
- G502
|
||||||
|
- G505
|
||||||
|
exclude-rules:
|
||||||
|
- path: internal/browser/browser\.go
|
||||||
|
linters:
|
||||||
|
- 'deadcode'
|
||||||
|
- 'varcheck'
|
||||||
|
- 'unused'
|
||||||
|
max-issues-per-linter: 0
|
||||||
|
max-same-issues: 0
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
module hack-browser-data
|
module hack-browser-data
|
||||||
|
|
||||||
go 1.18
|
go 1.19
|
||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/gocarina/gocsv v0.0.0-20211203214250-4735fba0c1d9
|
github.com/gocarina/gocsv v0.0.0-20211203214250-4735fba0c1d9
|
||||||
|
|||||||
@@ -6,14 +6,14 @@ import (
|
|||||||
"sort"
|
"sort"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/tidwall/gjson"
|
|
||||||
|
|
||||||
"hack-browser-data/internal/item"
|
"hack-browser-data/internal/item"
|
||||||
"hack-browser-data/internal/log"
|
"hack-browser-data/internal/log"
|
||||||
"hack-browser-data/internal/utils/fileutil"
|
"hack-browser-data/internal/utils/fileutil"
|
||||||
"hack-browser-data/internal/utils/typeutil"
|
"hack-browser-data/internal/utils/typeutil"
|
||||||
|
|
||||||
|
// import sqlite3 driver
|
||||||
_ "github.com/mattn/go-sqlite3"
|
_ "github.com/mattn/go-sqlite3"
|
||||||
|
"github.com/tidwall/gjson"
|
||||||
)
|
)
|
||||||
|
|
||||||
type ChromiumBookmark []bookmark
|
type ChromiumBookmark []bookmark
|
||||||
@@ -51,7 +51,7 @@ func getBookmarkChildren(value gjson.Result, w *ChromiumBookmark) (children gjso
|
|||||||
const (
|
const (
|
||||||
bookmarkID = "id"
|
bookmarkID = "id"
|
||||||
bookmarkAdded = "date_added"
|
bookmarkAdded = "date_added"
|
||||||
bookmarkUrl = "url"
|
bookmarkURL = "url"
|
||||||
bookmarkName = "name"
|
bookmarkName = "name"
|
||||||
bookmarkType = "type"
|
bookmarkType = "type"
|
||||||
bookmarkChildren = "children"
|
bookmarkChildren = "children"
|
||||||
@@ -60,7 +60,7 @@ func getBookmarkChildren(value gjson.Result, w *ChromiumBookmark) (children gjso
|
|||||||
bm := bookmark{
|
bm := bookmark{
|
||||||
ID: value.Get(bookmarkID).Int(),
|
ID: value.Get(bookmarkID).Int(),
|
||||||
Name: value.Get(bookmarkName).String(),
|
Name: value.Get(bookmarkName).String(),
|
||||||
URL: value.Get(bookmarkUrl).String(),
|
URL: value.Get(bookmarkURL).String(),
|
||||||
DateAdded: typeutil.TimeEpoch(value.Get(bookmarkAdded).Int()),
|
DateAdded: typeutil.TimeEpoch(value.Get(bookmarkAdded).Int()),
|
||||||
}
|
}
|
||||||
children = value.Get(bookmarkChildren)
|
children = value.Get(bookmarkChildren)
|
||||||
|
|||||||
@@ -53,17 +53,22 @@ func (d *Data) Output(dir, browserName, flag string) {
|
|||||||
// if the length of the export data is 0, then it is not necessary to output
|
// if the length of the export data is 0, then it is not necessary to output
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
filename := fileutil.Filename(browserName, source.Name(), output.Ext())
|
filename := fileutil.ItemName(browserName, source.Name(), output.Ext())
|
||||||
|
|
||||||
f, err := output.CreateFile(dir, filename)
|
f, err := output.CreateFile(dir, filename)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Errorf("create file error %s", err)
|
log.Errorf("create file %s error %s", filename, err.Error())
|
||||||
|
continue
|
||||||
}
|
}
|
||||||
if err := output.Write(source, f); err != nil {
|
if err := output.Write(source, f); err != nil {
|
||||||
log.Errorf("%s write to file %s error %s", source.Name(), filename, err.Error())
|
log.Errorf("write to file %s error %s", filename, err.Error())
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if err := f.Close(); err != nil {
|
||||||
|
log.Errorf("close file %s error %s", filename, err.Error())
|
||||||
|
continue
|
||||||
}
|
}
|
||||||
log.Noticef("output to file %s success", path.Join(dir, filename))
|
log.Noticef("output to file %s success", path.Join(dir, filename))
|
||||||
f.Close()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -6,12 +6,13 @@ import (
|
|||||||
"sort"
|
"sort"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
_ "github.com/mattn/go-sqlite3"
|
|
||||||
|
|
||||||
"hack-browser-data/internal/decrypter"
|
"hack-browser-data/internal/decrypter"
|
||||||
"hack-browser-data/internal/item"
|
"hack-browser-data/internal/item"
|
||||||
"hack-browser-data/internal/log"
|
"hack-browser-data/internal/log"
|
||||||
"hack-browser-data/internal/utils/typeutil"
|
"hack-browser-data/internal/utils/typeutil"
|
||||||
|
|
||||||
|
// import sqlite3 driver
|
||||||
|
_ "github.com/mattn/go-sqlite3"
|
||||||
)
|
)
|
||||||
|
|
||||||
type ChromiumCookie []cookie
|
type ChromiumCookie []cookie
|
||||||
@@ -72,7 +73,7 @@ func (c *ChromiumCookie) Parse(masterKey []byte) error {
|
|||||||
if len(encryptValue) > 0 {
|
if len(encryptValue) > 0 {
|
||||||
var err error
|
var err error
|
||||||
if masterKey == nil {
|
if masterKey == nil {
|
||||||
value, err = decrypter.DPApi(encryptValue)
|
value, err = decrypter.DPAPI(encryptValue)
|
||||||
} else {
|
} else {
|
||||||
value, err = decrypter.Chromium(masterKey, encryptValue)
|
value, err = decrypter.Chromium(masterKey, encryptValue)
|
||||||
}
|
}
|
||||||
@@ -118,10 +119,10 @@ func (f *FirefoxCookie) Parse(masterKey []byte) error {
|
|||||||
for rows.Next() {
|
for rows.Next() {
|
||||||
var (
|
var (
|
||||||
name, value, host, path string
|
name, value, host, path string
|
||||||
isSecure, isHttpOnly int
|
isSecure, isHTTPOnly int
|
||||||
creationTime, expiry int64
|
creationTime, expiry int64
|
||||||
)
|
)
|
||||||
if err = rows.Scan(&name, &value, &host, &path, &creationTime, &expiry, &isSecure, &isHttpOnly); err != nil {
|
if err = rows.Scan(&name, &value, &host, &path, &creationTime, &expiry, &isSecure, &isHTTPOnly); err != nil {
|
||||||
log.Warn(err)
|
log.Warn(err)
|
||||||
}
|
}
|
||||||
*f = append(*f, cookie{
|
*f = append(*f, cookie{
|
||||||
@@ -129,7 +130,7 @@ func (f *FirefoxCookie) Parse(masterKey []byte) error {
|
|||||||
Host: host,
|
Host: host,
|
||||||
Path: path,
|
Path: path,
|
||||||
IsSecure: typeutil.IntToBool(isSecure),
|
IsSecure: typeutil.IntToBool(isSecure),
|
||||||
IsHTTPOnly: typeutil.IntToBool(isHttpOnly),
|
IsHTTPOnly: typeutil.IntToBool(isHTTPOnly),
|
||||||
CreateDate: typeutil.TimeStamp(creationTime / 1000000),
|
CreateDate: typeutil.TimeStamp(creationTime / 1000000),
|
||||||
ExpireDate: typeutil.TimeStamp(expiry),
|
ExpireDate: typeutil.TimeStamp(expiry),
|
||||||
Value: value,
|
Value: value,
|
||||||
|
|||||||
@@ -4,11 +4,12 @@ import (
|
|||||||
"database/sql"
|
"database/sql"
|
||||||
"os"
|
"os"
|
||||||
|
|
||||||
_ "github.com/mattn/go-sqlite3"
|
|
||||||
|
|
||||||
"hack-browser-data/internal/decrypter"
|
"hack-browser-data/internal/decrypter"
|
||||||
"hack-browser-data/internal/item"
|
"hack-browser-data/internal/item"
|
||||||
"hack-browser-data/internal/log"
|
"hack-browser-data/internal/log"
|
||||||
|
|
||||||
|
// import sqlite3 driver
|
||||||
|
_ "github.com/mattn/go-sqlite3"
|
||||||
)
|
)
|
||||||
|
|
||||||
type ChromiumCreditCard []card
|
type ChromiumCreditCard []card
|
||||||
@@ -56,7 +57,7 @@ func (c *ChromiumCreditCard) Parse(masterKey []byte) error {
|
|||||||
NickName: nickname,
|
NickName: nickname,
|
||||||
}
|
}
|
||||||
if masterKey == nil {
|
if masterKey == nil {
|
||||||
value, err = decrypter.DPApi(encryptValue)
|
value, err = decrypter.DPAPI(encryptValue)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -112,7 +113,7 @@ func (c *YandexCreditCard) Parse(masterKey []byte) error {
|
|||||||
NickName: nickname,
|
NickName: nickname,
|
||||||
}
|
}
|
||||||
if masterKey == nil {
|
if masterKey == nil {
|
||||||
value, err = decrypter.DPApi(encryptValue)
|
value, err = decrypter.DPAPI(encryptValue)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ import (
|
|||||||
"hack-browser-data/internal/log"
|
"hack-browser-data/internal/log"
|
||||||
"hack-browser-data/internal/utils/typeutil"
|
"hack-browser-data/internal/utils/typeutil"
|
||||||
|
|
||||||
|
// import sqlite3 driver
|
||||||
_ "github.com/mattn/go-sqlite3"
|
_ "github.com/mattn/go-sqlite3"
|
||||||
"github.com/tidwall/gjson"
|
"github.com/tidwall/gjson"
|
||||||
)
|
)
|
||||||
@@ -19,7 +20,7 @@ type ChromiumDownload []download
|
|||||||
|
|
||||||
type download struct {
|
type download struct {
|
||||||
TargetPath string
|
TargetPath string
|
||||||
Url string
|
URL string
|
||||||
TotalBytes int64
|
TotalBytes int64
|
||||||
StartTime time.Time
|
StartTime time.Time
|
||||||
EndTime time.Time
|
EndTime time.Time
|
||||||
@@ -44,15 +45,15 @@ func (c *ChromiumDownload) Parse(masterKey []byte) error {
|
|||||||
defer rows.Close()
|
defer rows.Close()
|
||||||
for rows.Next() {
|
for rows.Next() {
|
||||||
var (
|
var (
|
||||||
targetPath, tabUrl, mimeType string
|
targetPath, tabURL, mimeType string
|
||||||
totalBytes, startTime, endTime int64
|
totalBytes, startTime, endTime int64
|
||||||
)
|
)
|
||||||
if err := rows.Scan(&targetPath, &tabUrl, &totalBytes, &startTime, &endTime, &mimeType); err != nil {
|
if err := rows.Scan(&targetPath, &tabURL, &totalBytes, &startTime, &endTime, &mimeType); err != nil {
|
||||||
log.Warn(err)
|
log.Warn(err)
|
||||||
}
|
}
|
||||||
data := download{
|
data := download{
|
||||||
TargetPath: targetPath,
|
TargetPath: targetPath,
|
||||||
Url: tabUrl,
|
URL: tabURL,
|
||||||
TotalBytes: totalBytes,
|
TotalBytes: totalBytes,
|
||||||
StartTime: typeutil.TimeEpoch(startTime),
|
StartTime: typeutil.TimeEpoch(startTime),
|
||||||
EndTime: typeutil.TimeEpoch(endTime),
|
EndTime: typeutil.TimeEpoch(endTime),
|
||||||
@@ -119,7 +120,7 @@ func (f *FirefoxDownload) Parse(masterKey []byte) error {
|
|||||||
fileSize := gjson.Get(json, "fileSize")
|
fileSize := gjson.Get(json, "fileSize")
|
||||||
*f = append(*f, download{
|
*f = append(*f, download{
|
||||||
TargetPath: path,
|
TargetPath: path,
|
||||||
Url: url,
|
URL: url,
|
||||||
TotalBytes: fileSize.Int(),
|
TotalBytes: fileSize.Int(),
|
||||||
StartTime: typeutil.TimeStamp(dateAdded / 1000000),
|
StartTime: typeutil.TimeStamp(dateAdded / 1000000),
|
||||||
EndTime: typeutil.TimeStamp(endTime.Int() / 1000),
|
EndTime: typeutil.TimeStamp(endTime.Int() / 1000),
|
||||||
|
|||||||
@@ -3,11 +3,11 @@ package extension
|
|||||||
import (
|
import (
|
||||||
"os"
|
"os"
|
||||||
|
|
||||||
"github.com/tidwall/gjson"
|
|
||||||
|
|
||||||
"hack-browser-data/internal/item"
|
"hack-browser-data/internal/item"
|
||||||
"hack-browser-data/internal/log"
|
"hack-browser-data/internal/log"
|
||||||
"hack-browser-data/internal/utils/fileutil"
|
"hack-browser-data/internal/utils/fileutil"
|
||||||
|
|
||||||
|
"github.com/tidwall/gjson"
|
||||||
)
|
)
|
||||||
|
|
||||||
type ChromiumExtension []*extension
|
type ChromiumExtension []*extension
|
||||||
|
|||||||
@@ -6,18 +6,19 @@ import (
|
|||||||
"sort"
|
"sort"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
_ "github.com/mattn/go-sqlite3"
|
|
||||||
|
|
||||||
"hack-browser-data/internal/item"
|
"hack-browser-data/internal/item"
|
||||||
"hack-browser-data/internal/log"
|
"hack-browser-data/internal/log"
|
||||||
"hack-browser-data/internal/utils/typeutil"
|
"hack-browser-data/internal/utils/typeutil"
|
||||||
|
|
||||||
|
// import sqlite3 driver
|
||||||
|
_ "github.com/mattn/go-sqlite3"
|
||||||
)
|
)
|
||||||
|
|
||||||
type ChromiumHistory []history
|
type ChromiumHistory []history
|
||||||
|
|
||||||
type history struct {
|
type history struct {
|
||||||
Title string
|
Title string
|
||||||
Url string
|
URL string
|
||||||
VisitCount int
|
VisitCount int
|
||||||
LastVisitTime time.Time
|
LastVisitTime time.Time
|
||||||
}
|
}
|
||||||
@@ -48,7 +49,7 @@ func (c *ChromiumHistory) Parse(masterKey []byte) error {
|
|||||||
log.Warn(err)
|
log.Warn(err)
|
||||||
}
|
}
|
||||||
data := history{
|
data := history{
|
||||||
Url: url,
|
URL: url,
|
||||||
Title: title,
|
Title: title,
|
||||||
VisitCount: visitCount,
|
VisitCount: visitCount,
|
||||||
LastVisitTime: typeutil.TimeEpoch(lastVisitTime),
|
LastVisitTime: typeutil.TimeEpoch(lastVisitTime),
|
||||||
@@ -109,7 +110,7 @@ func (f *FirefoxHistory) Parse(masterKey []byte) error {
|
|||||||
}
|
}
|
||||||
*f = append(*f, history{
|
*f = append(*f, history{
|
||||||
Title: title,
|
Title: title,
|
||||||
Url: url,
|
URL: url,
|
||||||
VisitCount: visitCount,
|
VisitCount: visitCount,
|
||||||
LastVisitTime: typeutil.TimeStamp(visitDate / 1000000),
|
LastVisitTime: typeutil.TimeStamp(visitDate / 1000000),
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -7,11 +7,11 @@ import (
|
|||||||
"os"
|
"os"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/syndtr/goleveldb/leveldb"
|
|
||||||
|
|
||||||
"hack-browser-data/internal/item"
|
"hack-browser-data/internal/item"
|
||||||
"hack-browser-data/internal/log"
|
"hack-browser-data/internal/log"
|
||||||
"hack-browser-data/internal/utils/typeutil"
|
"hack-browser-data/internal/utils/typeutil"
|
||||||
|
|
||||||
|
"github.com/syndtr/goleveldb/leveldb"
|
||||||
)
|
)
|
||||||
|
|
||||||
type ChromiumLocalStorage []storage
|
type ChromiumLocalStorage []storage
|
||||||
|
|||||||
@@ -52,7 +52,7 @@ func (o *OutPutter) CreateFile(dir, filename string) (*os.File, error) {
|
|||||||
|
|
||||||
if dir != "" {
|
if dir != "" {
|
||||||
if _, err := os.Stat(dir); os.IsNotExist(err) {
|
if _, err := os.Stat(dir); os.IsNotExist(err) {
|
||||||
err := os.MkdirAll(dir, 0o777)
|
err := os.MkdirAll(dir, 0o750)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@@ -62,7 +62,7 @@ func (o *OutPutter) CreateFile(dir, filename string) (*os.File, error) {
|
|||||||
var file *os.File
|
var file *os.File
|
||||||
var err error
|
var err error
|
||||||
p := filepath.Join(dir, filename)
|
p := filepath.Join(dir, filename)
|
||||||
file, err = os.OpenFile(p, os.O_TRUNC|os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0o666)
|
file, err = os.OpenFile(filepath.Clean(p), os.O_TRUNC|os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0o600)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@@ -72,7 +72,6 @@ func (o *OutPutter) CreateFile(dir, filename string) (*os.File, error) {
|
|||||||
func (o *OutPutter) Ext() string {
|
func (o *OutPutter) Ext() string {
|
||||||
if o.json {
|
if o.json {
|
||||||
return "json"
|
return "json"
|
||||||
} else {
|
|
||||||
return "csv"
|
|
||||||
}
|
}
|
||||||
|
return "csv"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func TestNewOutPutter(t *testing.T) {
|
func TestNewOutPutter(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
out := NewOutPutter("json")
|
out := NewOutPutter("json")
|
||||||
if out == nil {
|
if out == nil {
|
||||||
t.Error("New() returned nil")
|
t.Error("New() returned nil")
|
||||||
|
|||||||
@@ -4,18 +4,18 @@ import (
|
|||||||
"bytes"
|
"bytes"
|
||||||
"database/sql"
|
"database/sql"
|
||||||
"encoding/base64"
|
"encoding/base64"
|
||||||
"io/ioutil"
|
|
||||||
"os"
|
"os"
|
||||||
"sort"
|
"sort"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
_ "github.com/mattn/go-sqlite3"
|
|
||||||
"github.com/tidwall/gjson"
|
|
||||||
|
|
||||||
"hack-browser-data/internal/decrypter"
|
"hack-browser-data/internal/decrypter"
|
||||||
"hack-browser-data/internal/item"
|
"hack-browser-data/internal/item"
|
||||||
"hack-browser-data/internal/log"
|
"hack-browser-data/internal/log"
|
||||||
"hack-browser-data/internal/utils/typeutil"
|
"hack-browser-data/internal/utils/typeutil"
|
||||||
|
|
||||||
|
// import sqlite3 driver
|
||||||
|
_ "github.com/mattn/go-sqlite3"
|
||||||
|
"github.com/tidwall/gjson"
|
||||||
)
|
)
|
||||||
|
|
||||||
type ChromiumPassword []loginData
|
type ChromiumPassword []loginData
|
||||||
@@ -25,7 +25,7 @@ type loginData struct {
|
|||||||
encryptPass []byte
|
encryptPass []byte
|
||||||
encryptUser []byte
|
encryptUser []byte
|
||||||
Password string
|
Password string
|
||||||
LoginUrl string
|
LoginURL string
|
||||||
CreateDate time.Time
|
CreateDate time.Time
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -58,12 +58,12 @@ func (c *ChromiumPassword) Parse(masterKey []byte) error {
|
|||||||
login := loginData{
|
login := loginData{
|
||||||
UserName: username,
|
UserName: username,
|
||||||
encryptPass: pwd,
|
encryptPass: pwd,
|
||||||
LoginUrl: url,
|
LoginURL: url,
|
||||||
}
|
}
|
||||||
if len(pwd) > 0 {
|
if len(pwd) > 0 {
|
||||||
var err error
|
var err error
|
||||||
if masterKey == nil {
|
if masterKey == nil {
|
||||||
password, err = decrypter.DPApi(pwd)
|
password, err = decrypter.DPAPI(pwd)
|
||||||
} else {
|
} else {
|
||||||
password, err = decrypter.Chromium(masterKey, pwd)
|
password, err = decrypter.Chromium(masterKey, pwd)
|
||||||
}
|
}
|
||||||
@@ -125,13 +125,13 @@ func (c *YandexPassword) Parse(masterKey []byte) error {
|
|||||||
login := loginData{
|
login := loginData{
|
||||||
UserName: username,
|
UserName: username,
|
||||||
encryptPass: pwd,
|
encryptPass: pwd,
|
||||||
LoginUrl: url,
|
LoginURL: url,
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(pwd) > 0 {
|
if len(pwd) > 0 {
|
||||||
var err error
|
var err error
|
||||||
if masterKey == nil {
|
if masterKey == nil {
|
||||||
password, err = decrypter.DPApi(pwd)
|
password, err = decrypter.DPAPI(pwd)
|
||||||
} else {
|
} else {
|
||||||
password, err = decrypter.Chromium(masterKey, pwd)
|
password, err = decrypter.Chromium(masterKey, pwd)
|
||||||
}
|
}
|
||||||
@@ -196,7 +196,7 @@ func (f *FirefoxPassword) Parse(masterKey []byte) error {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
allLogin, err := getFirefoxLoginData(item.TempFirefoxPassword)
|
allLogin, err := getFirefoxLoginData()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -218,7 +218,7 @@ func (f *FirefoxPassword) Parse(masterKey []byte) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
*f = append(*f, loginData{
|
*f = append(*f, loginData{
|
||||||
LoginUrl: v.LoginUrl,
|
LoginURL: v.LoginURL,
|
||||||
UserName: string(user),
|
UserName: string(user),
|
||||||
Password: string(pwd),
|
Password: string(pwd),
|
||||||
CreateDate: v.CreateDate,
|
CreateDate: v.CreateDate,
|
||||||
@@ -251,12 +251,12 @@ func getFirefoxDecryptKey(key4file string) (item1, item2, a11, a102 []byte, err
|
|||||||
return item1, item2, a11, a102, nil
|
return item1, item2, a11, a102, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func getFirefoxLoginData(loginJson string) (l []loginData, err error) {
|
func getFirefoxLoginData() (l []loginData, err error) {
|
||||||
s, err := ioutil.ReadFile(loginJson)
|
s, err := os.ReadFile(item.TempFirefoxPassword)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
defer os.Remove(loginJson)
|
defer os.Remove(item.TempFirefoxPassword)
|
||||||
h := gjson.GetBytes(s, "logins")
|
h := gjson.GetBytes(s, "logins")
|
||||||
if h.Exists() {
|
if h.Exists() {
|
||||||
for _, v := range h.Array() {
|
for _, v := range h.Array() {
|
||||||
@@ -265,7 +265,7 @@ func getFirefoxLoginData(loginJson string) (l []loginData, err error) {
|
|||||||
user []byte
|
user []byte
|
||||||
pass []byte
|
pass []byte
|
||||||
)
|
)
|
||||||
m.LoginUrl = v.Get("formSubmitURL").String()
|
m.LoginURL = v.Get("formSubmitURL").String()
|
||||||
user, err = base64.StdEncoding.DecodeString(v.Get("encryptedUsername").String())
|
user, err = base64.StdEncoding.DecodeString(v.Get("encryptedUsername").String())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
|||||||
@@ -119,14 +119,13 @@ const (
|
|||||||
chromeBetaName = "Chrome Beta"
|
chromeBetaName = "Chrome Beta"
|
||||||
chromiumName = "Chromium"
|
chromiumName = "Chromium"
|
||||||
edgeName = "Microsoft Edge"
|
edgeName = "Microsoft Edge"
|
||||||
speed360Name = "360speed"
|
|
||||||
qqBrowserName = "QQ"
|
|
||||||
braveName = "Brave"
|
braveName = "Brave"
|
||||||
operaName = "Opera"
|
operaName = "Opera"
|
||||||
operaGXName = "OperaGX"
|
operaGXName = "OperaGX"
|
||||||
vivaldiName = "Vivaldi"
|
vivaldiName = "Vivaldi"
|
||||||
coccocName = "CocCoc"
|
coccocName = "CocCoc"
|
||||||
yandexName = "Yandex"
|
yandexName = "Yandex"
|
||||||
|
firefoxName = "Firefox"
|
||||||
firefoxName = "Firefox"
|
speed360Name = "360speed"
|
||||||
|
qqBrowserName = "QQ"
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -32,7 +32,7 @@ func New(name, storage, profilePath string, items []item.Item) ([]*chromium, err
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
var chromiumList []*chromium
|
chromiumList := make([]*chromium, 0, len(multiItemPaths))
|
||||||
for user, itemPaths := range multiItemPaths {
|
for user, itemPaths := range multiItemPaths {
|
||||||
chromiumList = append(chromiumList, &chromium{
|
chromiumList = append(chromiumList, &chromium{
|
||||||
name: fileutil.BrowserName(name, user),
|
name: fileutil.BrowserName(name, user),
|
||||||
|
|||||||
@@ -28,10 +28,9 @@ func (c *chromium) GetMasterKey() ([]byte, error) {
|
|||||||
)
|
)
|
||||||
// don't need chromium key file for macOS
|
// don't need chromium key file for macOS
|
||||||
defer os.Remove(item.TempChromiumKey)
|
defer os.Remove(item.TempChromiumKey)
|
||||||
// defer os.Remove(item.TempChromiumKey)
|
|
||||||
// Get the master key from the keychain
|
// Get the master key from the keychain
|
||||||
// $ security find-generic-password -wa 'Chrome'
|
// $ security find-generic-password -wa 'Chrome'
|
||||||
cmd = exec.Command("security", "find-generic-password", "-wa", c.storage)
|
cmd = exec.Command("security", "find-generic-password", "-wa", strings.TrimSpace(c.storage)) //nolint:gosec
|
||||||
cmd.Stdout = &stdout
|
cmd.Stdout = &stdout
|
||||||
cmd.Stderr = &stderr
|
cmd.Stderr = &stderr
|
||||||
err := cmd.Run()
|
err := cmd.Run()
|
||||||
|
|||||||
@@ -32,7 +32,9 @@ func (c *chromium) GetMasterKey() ([]byte, error) {
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
defer func() {
|
defer func() {
|
||||||
session.Close()
|
if err := session.Close(); err != nil {
|
||||||
|
log.Errorf("close session failed: %v", err)
|
||||||
|
}
|
||||||
}()
|
}()
|
||||||
collections, err := svc.GetAllCollections()
|
collections, err := svc.GetAllCollections()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|||||||
@@ -24,14 +24,14 @@ func (c *chromium) GetMasterKey() ([]byte, error) {
|
|||||||
}
|
}
|
||||||
defer os.Remove(keyFile)
|
defer os.Remove(keyFile)
|
||||||
encryptedKey := gjson.Get(keyFile, "os_crypt.encrypted_key")
|
encryptedKey := gjson.Get(keyFile, "os_crypt.encrypted_key")
|
||||||
if encryptedKey.Exists() {
|
if !encryptedKey.Exists() {
|
||||||
pureKey, err := base64.StdEncoding.DecodeString(encryptedKey.String())
|
return nil, nil
|
||||||
if err != nil {
|
|
||||||
return nil, errDecodeMasterKeyFailed
|
|
||||||
}
|
|
||||||
c.masterKey, err = decrypter.DPApi(pureKey[5:])
|
|
||||||
log.Infof("%s initialized master key success", c.name)
|
|
||||||
return c.masterKey, err
|
|
||||||
}
|
}
|
||||||
return nil, nil
|
pureKey, err := base64.StdEncoding.DecodeString(encryptedKey.String())
|
||||||
|
if err != nil {
|
||||||
|
return nil, errDecodeMasterKeyFailed
|
||||||
|
}
|
||||||
|
c.masterKey, err = decrypter.DPAPI(pureKey[5:])
|
||||||
|
log.Infof("%s initialized master key success", c.name)
|
||||||
|
return c.masterKey, err
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -35,7 +35,8 @@ func New(name, storage, profilePath string, items []item.Item) ([]*firefox, erro
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
var firefoxList []*firefox
|
|
||||||
|
firefoxList := make([]*firefox, 0, len(multiItemPaths))
|
||||||
for name, itemPaths := range multiItemPaths {
|
for name, itemPaths := range multiItemPaths {
|
||||||
firefoxList = append(firefoxList, &firefox{
|
firefoxList = append(firefoxList, &firefox{
|
||||||
name: fmt.Sprintf("firefox-%s", name),
|
name: fmt.Sprintf("firefox-%s", name),
|
||||||
|
|||||||
@@ -14,11 +14,9 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
errSecurityKeyIsEmpty = errors.New("input [security find-generic-password -wa 'Chrome'] in terminal")
|
errPasswordIsEmpty = errors.New("password is empty")
|
||||||
errPasswordIsEmpty = errors.New("password is empty")
|
errDecodeASN1Failed = errors.New("decode ASN1 data failed")
|
||||||
errDecryptFailed = errors.New("decrypt encrypted value failed")
|
errEncryptedLength = errors.New("length of encrypted password less than block size")
|
||||||
errDecodeASN1Failed = errors.New("decode ASN1 data failed")
|
|
||||||
errEncryptedLength = errors.New("length of encrypted password less than block size")
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type ASN1PBE interface {
|
type ASN1PBE interface {
|
||||||
@@ -44,13 +42,13 @@ func NewASN1PBE(b []byte) (pbe ASN1PBE, err error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// nssPBE Struct
|
// nssPBE Struct
|
||||||
// SEQUENCE (2 elem)
|
//
|
||||||
// SEQUENCE (2 elem)
|
// SEQUENCE (2 elem)
|
||||||
// OBJECT IDENTIFIER
|
// OBJECT IDENTIFIER
|
||||||
// SEQUENCE (2 elem)
|
// SEQUENCE (2 elem)
|
||||||
// OCTET STRING (20 byte)
|
// OCTET STRING (20 byte)
|
||||||
// INTEGER 1
|
// INTEGER 1
|
||||||
// OCTET STRING (16 byte)
|
// OCTET STRING (16 byte)
|
||||||
type nssPBE struct {
|
type nssPBE struct {
|
||||||
AlgoAttr struct {
|
AlgoAttr struct {
|
||||||
asn1.ObjectIdentifier
|
asn1.ObjectIdentifier
|
||||||
@@ -62,10 +60,6 @@ type nssPBE struct {
|
|||||||
Encrypted []byte
|
Encrypted []byte
|
||||||
}
|
}
|
||||||
|
|
||||||
func (n nssPBE) entrySalt() []byte {
|
|
||||||
return n.AlgoAttr.SaltAttr.EntrySalt
|
|
||||||
}
|
|
||||||
|
|
||||||
func (n nssPBE) Decrypt(globalSalt, masterPwd []byte) (key []byte, err error) {
|
func (n nssPBE) Decrypt(globalSalt, masterPwd []byte) (key []byte, err error) {
|
||||||
glmp := append(globalSalt, masterPwd...)
|
glmp := append(globalSalt, masterPwd...)
|
||||||
hp := sha1.Sum(glmp)
|
hp := sha1.Sum(glmp)
|
||||||
@@ -82,26 +76,34 @@ func (n nssPBE) Decrypt(globalSalt, masterPwd []byte) (key []byte, err error) {
|
|||||||
k2.Write(tkPlus)
|
k2.Write(tkPlus)
|
||||||
k := append(k1.Sum(nil), k2.Sum(nil)...)
|
k := append(k1.Sum(nil), k2.Sum(nil)...)
|
||||||
iv := k[len(k)-8:]
|
iv := k[len(k)-8:]
|
||||||
return des3Decrypt(k[:24], iv, n.Encrypted)
|
return des3Decrypt(k[:24], iv, n.encrypted())
|
||||||
|
}
|
||||||
|
|
||||||
|
func (n nssPBE) entrySalt() []byte {
|
||||||
|
return n.AlgoAttr.SaltAttr.EntrySalt
|
||||||
|
}
|
||||||
|
|
||||||
|
func (n nssPBE) encrypted() []byte {
|
||||||
|
return n.Encrypted
|
||||||
}
|
}
|
||||||
|
|
||||||
// MetaPBE Struct
|
// MetaPBE Struct
|
||||||
// SEQUENCE (2 elem)
|
//
|
||||||
// SEQUENCE (2 elem)
|
// SEQUENCE (2 elem)
|
||||||
// OBJECT IDENTIFIER
|
// OBJECT IDENTIFIER
|
||||||
// SEQUENCE (2 elem)
|
// SEQUENCE (2 elem)
|
||||||
// SEQUENCE (2 elem)
|
// SEQUENCE (2 elem)
|
||||||
// OBJECT IDENTIFIER
|
// OBJECT IDENTIFIER
|
||||||
// SEQUENCE (4 elem)
|
// SEQUENCE (4 elem)
|
||||||
// OCTET STRING (32 byte)
|
// OCTET STRING (32 byte)
|
||||||
// INTEGER 1
|
// INTEGER 1
|
||||||
// INTEGER 32
|
// INTEGER 32
|
||||||
// SEQUENCE (1 elem)
|
// SEQUENCE (1 elem)
|
||||||
// OBJECT IDENTIFIER
|
// OBJECT IDENTIFIER
|
||||||
// SEQUENCE (2 elem)
|
// SEQUENCE (2 elem)
|
||||||
// OBJECT IDENTIFIER
|
// OBJECT IDENTIFIER
|
||||||
// OCTET STRING (14 byte)
|
// OCTET STRING (14 byte)
|
||||||
// OCTET STRING (16 byte)
|
// OCTET STRING (16 byte)
|
||||||
type metaPBE struct {
|
type metaPBE struct {
|
||||||
AlgoAttr algoAttr
|
AlgoAttr algoAttr
|
||||||
Encrypted []byte
|
Encrypted []byte
|
||||||
@@ -135,8 +137,8 @@ type slatAttr struct {
|
|||||||
func (m metaPBE) Decrypt(globalSalt, masterPwd []byte) (key2 []byte, err error) {
|
func (m metaPBE) Decrypt(globalSalt, masterPwd []byte) (key2 []byte, err error) {
|
||||||
k := sha1.Sum(globalSalt)
|
k := sha1.Sum(globalSalt)
|
||||||
key := pbkdf2.Key(k[:], m.entrySalt(), m.iterationCount(), m.keySize(), sha256.New)
|
key := pbkdf2.Key(k[:], m.entrySalt(), m.iterationCount(), m.keySize(), sha256.New)
|
||||||
iv := append([]byte{4, 14}, m.AlgoAttr.Data.IVData.IV...)
|
iv := append([]byte{4, 14}, m.iv()...)
|
||||||
return aes128CBCDecrypt(key, iv, m.Encrypted)
|
return aes128CBCDecrypt(key, iv, m.encrypted())
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m metaPBE) entrySalt() []byte {
|
func (m metaPBE) entrySalt() []byte {
|
||||||
@@ -151,13 +153,21 @@ func (m metaPBE) keySize() int {
|
|||||||
return m.AlgoAttr.Data.Data.SlatAttr.KeySize
|
return m.AlgoAttr.Data.Data.SlatAttr.KeySize
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (m metaPBE) iv() []byte {
|
||||||
|
return m.AlgoAttr.Data.IVData.IV
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m metaPBE) encrypted() []byte {
|
||||||
|
return m.Encrypted
|
||||||
|
}
|
||||||
|
|
||||||
// loginPBE Struct
|
// loginPBE Struct
|
||||||
// SEQUENCE (3 elem)
|
//
|
||||||
// OCTET STRING (16 byte)
|
// OCTET STRING (16 byte)
|
||||||
// SEQUENCE (2 elem)
|
// SEQUENCE (2 elem)
|
||||||
// OBJECT IDENTIFIER
|
// OBJECT IDENTIFIER
|
||||||
// OCTET STRING (8 byte)
|
// OCTET STRING (8 byte)
|
||||||
// OCTET STRING (16 byte)
|
// OCTET STRING (16 byte)
|
||||||
type loginPBE struct {
|
type loginPBE struct {
|
||||||
CipherText []byte
|
CipherText []byte
|
||||||
Data struct {
|
Data struct {
|
||||||
@@ -168,7 +178,15 @@ type loginPBE struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (l loginPBE) Decrypt(globalSalt, masterPwd []byte) (key []byte, err error) {
|
func (l loginPBE) Decrypt(globalSalt, masterPwd []byte) (key []byte, err error) {
|
||||||
return des3Decrypt(globalSalt, l.Data.IV, l.Encrypted)
|
return des3Decrypt(globalSalt, l.iv(), l.encrypted())
|
||||||
|
}
|
||||||
|
|
||||||
|
func (l loginPBE) iv() []byte {
|
||||||
|
return l.Data.IV
|
||||||
|
}
|
||||||
|
|
||||||
|
func (l loginPBE) encrypted() []byte {
|
||||||
|
return l.Encrypted
|
||||||
}
|
}
|
||||||
|
|
||||||
func aes128CBCDecrypt(key, iv, encryptPass []byte) ([]byte, error) {
|
func aes128CBCDecrypt(key, iv, encryptPass []byte) ([]byte, error) {
|
||||||
@@ -197,7 +215,7 @@ func pkcs5UnPadding(src []byte, blockSize int) []byte {
|
|||||||
return src[:n-paddingNum]
|
return src[:n-paddingNum]
|
||||||
}
|
}
|
||||||
|
|
||||||
// des3Decrypt use for decrypter firefox PBE
|
// des3Decrypt use for decrypt firefox PBE
|
||||||
func des3Decrypt(key, iv []byte, src []byte) ([]byte, error) {
|
func des3Decrypt(key, iv []byte, src []byte) ([]byte, error) {
|
||||||
block, err := des.NewTripleDESCipher(key)
|
block, err := des.NewTripleDESCipher(key)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -213,10 +231,9 @@ func paddingZero(s []byte, l int) []byte {
|
|||||||
h := l - len(s)
|
h := l - len(s)
|
||||||
if h <= 0 {
|
if h <= 0 {
|
||||||
return s
|
return s
|
||||||
} else {
|
|
||||||
for i := len(s); i < l; i++ {
|
|
||||||
s = append(s, 0)
|
|
||||||
}
|
|
||||||
return s
|
|
||||||
}
|
}
|
||||||
|
for i := len(s); i < l; i++ {
|
||||||
|
s = append(s, 0)
|
||||||
|
}
|
||||||
|
return s
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,17 +1,21 @@
|
|||||||
package decrypter
|
package decrypter
|
||||||
|
|
||||||
|
var (
|
||||||
|
errSecurityKeyIsEmpty = errors.New("input [security find-generic-password -wa 'Chrome'] in terminal")
|
||||||
|
)
|
||||||
|
|
||||||
func Chromium(key, encryptPass []byte) ([]byte, error) {
|
func Chromium(key, encryptPass []byte) ([]byte, error) {
|
||||||
if len(encryptPass) > 3 {
|
if len(encryptPass) <= 3 {
|
||||||
if len(key) == 0 {
|
return nil, errPasswordIsEmpty
|
||||||
return nil, errSecurityKeyIsEmpty
|
|
||||||
}
|
|
||||||
chromeIV := []byte{32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32}
|
|
||||||
return aes128CBCDecrypt(key, chromeIV, encryptPass[3:])
|
|
||||||
} else {
|
|
||||||
return nil, errDecryptFailed
|
|
||||||
}
|
}
|
||||||
|
if len(key) == 0 {
|
||||||
|
return nil, errSecurityKeyIsEmpty
|
||||||
|
}
|
||||||
|
|
||||||
|
iv := []byte{32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32}
|
||||||
|
return aes128CBCDecrypt(key, iv, encryptPass[3:])
|
||||||
}
|
}
|
||||||
|
|
||||||
func DPApi(data []byte) ([]byte, error) {
|
func DPAPI(data []byte) ([]byte, error) {
|
||||||
return nil, nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,17 +1,14 @@
|
|||||||
package decrypter
|
package decrypter
|
||||||
|
|
||||||
func Chromium(key, encryptPass []byte) ([]byte, error) {
|
func Chromium(key, encryptPass []byte) ([]byte, error) {
|
||||||
chromeIV := []byte{32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32}
|
if len(encryptPass) < 3 {
|
||||||
if len(encryptPass) > 3 {
|
return nil, errPasswordIsEmpty
|
||||||
if len(key) == 0 {
|
|
||||||
return nil, errSecurityKeyIsEmpty
|
|
||||||
}
|
|
||||||
return aes128CBCDecrypt(key, chromeIV, encryptPass[3:])
|
|
||||||
} else {
|
|
||||||
return nil, errDecryptFailed
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
chromeIV := []byte{32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, 32}
|
||||||
|
return aes128CBCDecrypt(key, chromeIV, encryptPass[3:])
|
||||||
}
|
}
|
||||||
|
|
||||||
func DPApi(data []byte) ([]byte, error) {
|
func DPAPI(data []byte) ([]byte, error) {
|
||||||
return nil, nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,25 +8,29 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func Chromium(key, encryptPass []byte) ([]byte, error) {
|
func Chromium(key, encryptPass []byte) ([]byte, error) {
|
||||||
if len(encryptPass) > 15 {
|
if len(encryptPass) < 3 {
|
||||||
// remove Prefix 'v10'
|
|
||||||
return aesGCMDecrypt(encryptPass[15:], key, encryptPass[3:15])
|
|
||||||
} else {
|
|
||||||
return nil, errPasswordIsEmpty
|
return nil, errPasswordIsEmpty
|
||||||
}
|
}
|
||||||
|
if len(key) == 0 {
|
||||||
|
return nil, errSecurityKeyIsEmpty
|
||||||
|
}
|
||||||
|
|
||||||
|
return aesGCMDecrypt(encryptPass[15:], key, encryptPass[3:15])
|
||||||
}
|
}
|
||||||
|
|
||||||
func ChromiumForYandex(key, encryptPass []byte) ([]byte, error) {
|
func ChromiumForYandex(key, encryptPass []byte) ([]byte, error) {
|
||||||
if len(encryptPass) > 15 {
|
if len(encryptPass) < 3 {
|
||||||
// remove Prefix 'v10'
|
|
||||||
// gcmBlockSize = 16
|
|
||||||
// gcmTagSize = 16
|
|
||||||
// gcmMinimumTagSize = 12 // NIST SP 800-38D recommends tags with 12 or more bytes.
|
|
||||||
// gcmStandardNonceSize = 12
|
|
||||||
return aesGCMDecrypt(encryptPass[12:], key, encryptPass[0:12])
|
|
||||||
} else {
|
|
||||||
return nil, errPasswordIsEmpty
|
return nil, errPasswordIsEmpty
|
||||||
}
|
}
|
||||||
|
if len(key) == 0 {
|
||||||
|
return nil, errSecurityKeyIsEmpty
|
||||||
|
}
|
||||||
|
// remove Prefix 'v10'
|
||||||
|
// gcmBlockSize = 16
|
||||||
|
// gcmTagSize = 16
|
||||||
|
// gcmMinimumTagSize = 12 // NIST SP 800-38D recommends tags with 12 or more bytes.
|
||||||
|
// gcmStandardNonceSize = 12
|
||||||
|
return aesGCMDecrypt(encryptPass[12:], key, encryptPass[0:12])
|
||||||
}
|
}
|
||||||
|
|
||||||
// chromium > 80 https://source.chromium.org/chromium/chromium/src/+/master:components/os_crypt/os_crypt_win.cc
|
// chromium > 80 https://source.chromium.org/chromium/chromium/src/+/master:components/os_crypt/os_crypt_win.cc
|
||||||
@@ -67,9 +71,12 @@ func (b *dataBlob) ToByteArray() []byte {
|
|||||||
return d
|
return d
|
||||||
}
|
}
|
||||||
|
|
||||||
// DPApi
|
// DPAPI (Data Protection Application Programming Interface)
|
||||||
|
// is a simple cryptographic application programming interface
|
||||||
|
// available as a built-in component in Windows 2000 and
|
||||||
|
// later versions of Microsoft Windows operating systems
|
||||||
// chrome < 80 https://chromium.googlesource.com/chromium/src/+/76f496a7235c3432983421402951d73905c8be96/components/os_crypt/os_crypt_win.cc#82
|
// chrome < 80 https://chromium.googlesource.com/chromium/src/+/76f496a7235c3432983421402951d73905c8be96/components/os_crypt/os_crypt_win.cc#82
|
||||||
func DPApi(data []byte) ([]byte, error) {
|
func DPAPI(data []byte) ([]byte, error) {
|
||||||
dllCrypt := syscall.NewLazyDLL("Crypt32.dll")
|
dllCrypt := syscall.NewLazyDLL("Crypt32.dll")
|
||||||
dllKernel := syscall.NewLazyDLL("Kernel32.dll")
|
dllKernel := syscall.NewLazyDLL("Kernel32.dll")
|
||||||
procDecryptData := dllCrypt.NewProc("CryptUnprotectData")
|
procDecryptData := dllCrypt.NewProc("CryptUnprotectData")
|
||||||
|
|||||||
@@ -5,7 +5,6 @@ import (
|
|||||||
"bytes"
|
"bytes"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io/ioutil"
|
|
||||||
"os"
|
"os"
|
||||||
"path"
|
"path"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
@@ -55,7 +54,7 @@ func FilesInFolder(dir, filename string) ([]string, error) {
|
|||||||
|
|
||||||
// ReadFile reads the file from the provided path
|
// ReadFile reads the file from the provided path
|
||||||
func ReadFile(filename string) (string, error) {
|
func ReadFile(filename string) (string, error) {
|
||||||
s, err := ioutil.ReadFile(filename)
|
s, err := os.ReadFile(filename)
|
||||||
return string(s), err
|
return string(s), err
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -71,20 +70,20 @@ func CopyDir(src, dst, skip string) error {
|
|||||||
// CopyDirHasSuffix copies the directory from the source to the destination
|
// CopyDirHasSuffix copies the directory from the source to the destination
|
||||||
// contain is the file if you want to copy, and rename copied filename with dir/index_filename
|
// contain is the file if you want to copy, and rename copied filename with dir/index_filename
|
||||||
func CopyDirHasSuffix(src, dst, suffix string) error {
|
func CopyDirHasSuffix(src, dst, suffix string) error {
|
||||||
var filelist []string
|
var files []string
|
||||||
err := filepath.Walk(src, func(path string, f os.FileInfo, err error) error {
|
err := filepath.Walk(src, func(path string, f os.FileInfo, err error) error {
|
||||||
if !f.IsDir() && strings.HasSuffix(strings.ToLower(f.Name()), suffix) {
|
if !f.IsDir() && strings.HasSuffix(strings.ToLower(f.Name()), suffix) {
|
||||||
filelist = append(filelist, path)
|
files = append(files, path)
|
||||||
}
|
}
|
||||||
return err
|
return err
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if err := os.MkdirAll(dst, 0o755); err != nil {
|
if err := os.MkdirAll(dst, 0o700); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
for index, file := range filelist {
|
for index, file := range files {
|
||||||
// p = dir/index_file
|
// p = dir/index_file
|
||||||
p := fmt.Sprintf("%s/%d_%s", dst, index, BaseDir(file))
|
p := fmt.Sprintf("%s/%d_%s", dst, index, BaseDir(file))
|
||||||
err = CopyFile(file, p)
|
err = CopyFile(file, p)
|
||||||
@@ -97,20 +96,19 @@ func CopyDirHasSuffix(src, dst, suffix string) error {
|
|||||||
|
|
||||||
// CopyFile copies the file from the source to the destination
|
// CopyFile copies the file from the source to the destination
|
||||||
func CopyFile(src, dst string) error {
|
func CopyFile(src, dst string) error {
|
||||||
// TODO: Handle read file error
|
s, err := os.ReadFile(src)
|
||||||
d, err := ioutil.ReadFile(src)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
err = ioutil.WriteFile(dst, d, 0o777)
|
err = os.WriteFile(dst, s, 0o600)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Filename returns the filename from the provided path
|
// ItemName returns the filename from the provided path
|
||||||
func Filename(browser, item, ext string) string {
|
func ItemName(browser, item, ext string) string {
|
||||||
replace := strings.NewReplacer(" ", "_", ".", "_", "-", "_")
|
replace := strings.NewReplacer(" ", "_", ".", "_", "-", "_")
|
||||||
return strings.ToLower(fmt.Sprintf("%s_%s.%s", replace.Replace(browser), item, ext))
|
return strings.ToLower(fmt.Sprintf("%s_%s.%s", replace.Replace(browser), item, ext))
|
||||||
}
|
}
|
||||||
@@ -137,26 +135,27 @@ func ParentBaseDir(p string) string {
|
|||||||
|
|
||||||
// CompressDir compresses the directory into a zip file
|
// CompressDir compresses the directory into a zip file
|
||||||
func CompressDir(dir string) error {
|
func CompressDir(dir string) error {
|
||||||
files, err := ioutil.ReadDir(dir)
|
files, err := os.ReadDir(dir)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
b := new(bytes.Buffer)
|
b := new(bytes.Buffer)
|
||||||
zw := zip.NewWriter(b)
|
zw := zip.NewWriter(b)
|
||||||
for _, f := range files {
|
for _, f := range files {
|
||||||
fw, _ := zw.Create(f.Name())
|
fw, err := zw.Create(f.Name())
|
||||||
fileName := path.Join(dir, f.Name())
|
|
||||||
fileContent, err := ioutil.ReadFile(fileName)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
zw.Close()
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
_, err = fw.Write(fileContent)
|
name := path.Join(dir, f.Name())
|
||||||
|
content, err := os.ReadFile(name)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
zw.Close()
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
err = os.Remove(fileName)
|
_, err = fw.Write(content)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
err = os.Remove(name)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -165,7 +164,7 @@ func CompressDir(dir string) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
filename := filepath.Join(dir, fmt.Sprintf("%s.zip", dir))
|
filename := filepath.Join(dir, fmt.Sprintf("%s.zip", dir))
|
||||||
outFile, err := os.Create(filename)
|
outFile, err := os.Create(filepath.Clean(filename))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -173,5 +172,5 @@ func CompressDir(dir string) error {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
return nil
|
return outFile.Close()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,13 +4,15 @@ import (
|
|||||||
"testing"
|
"testing"
|
||||||
)
|
)
|
||||||
|
|
||||||
var reverseTestCases = [][]any{
|
|
||||||
{1, 2, 3, 4, 5},
|
|
||||||
{"1", "2", "3", "4", "5"},
|
|
||||||
{"1", 2, "3", "4", 5},
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestReverse(t *testing.T) {
|
func TestReverse(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
|
||||||
|
reverseTestCases := [][]any{
|
||||||
|
{1, 2, 3, 4, 5},
|
||||||
|
{"1", "2", "3", "4", "5"},
|
||||||
|
{"1", 2, "3", "4", 5},
|
||||||
|
}
|
||||||
|
|
||||||
for _, ts := range reverseTestCases {
|
for _, ts := range reverseTestCases {
|
||||||
h := Reverse(ts)
|
h := Reverse(ts)
|
||||||
for i := 0; i < len(ts); i++ {
|
for i := 0; i < len(ts); i++ {
|
||||||
|
|||||||
Reference in New Issue
Block a user