mirror of
https://github.com/moonD4rk/HackBrowserData.git
synced 2026-05-21 19:06:47 +02:00
chore: update golangci-lint config and fix lint issues (#542)
* chore: update golangci-lint config and fix lint issues
This commit is contained in:
+32
-66
@@ -10,7 +10,7 @@ run:
|
|||||||
linters:
|
linters:
|
||||||
default: none
|
default: none
|
||||||
enable:
|
enable:
|
||||||
# Default tier
|
# Default tier — must-have for any Go project
|
||||||
- errcheck
|
- errcheck
|
||||||
- govet
|
- govet
|
||||||
- staticcheck
|
- staticcheck
|
||||||
@@ -21,11 +21,18 @@ linters:
|
|||||||
- errorlint
|
- errorlint
|
||||||
- gosec
|
- gosec
|
||||||
- sqlclosecheck
|
- sqlclosecheck
|
||||||
|
- nilerr
|
||||||
|
- bodyclose
|
||||||
|
- durationcheck
|
||||||
|
- errchkjson
|
||||||
|
- exhaustive
|
||||||
|
- forcetypeassert
|
||||||
|
|
||||||
# Code quality
|
# Code quality
|
||||||
- depguard
|
- depguard
|
||||||
- dogsled
|
- dogsled
|
||||||
- dupl
|
- dupl
|
||||||
|
- dupword
|
||||||
- errname
|
- errname
|
||||||
- funlen
|
- funlen
|
||||||
- gocheckcompilerdirectives
|
- gocheckcompilerdirectives
|
||||||
@@ -35,20 +42,24 @@ linters:
|
|||||||
- godox
|
- godox
|
||||||
- goprintffuncname
|
- goprintffuncname
|
||||||
- lll
|
- lll
|
||||||
|
- mirror
|
||||||
- misspell
|
- misspell
|
||||||
- nakedret
|
- nakedret
|
||||||
|
- predeclared
|
||||||
- revive
|
- revive
|
||||||
- testifylint
|
- testifylint
|
||||||
- unconvert
|
- unconvert
|
||||||
- unparam
|
- unparam
|
||||||
- usestdlibvars
|
- usestdlibvars
|
||||||
|
- wastedassign
|
||||||
- whitespace
|
- whitespace
|
||||||
|
|
||||||
# Complexity
|
# Complexity
|
||||||
- gocognit
|
- gocognit
|
||||||
|
- nestif
|
||||||
|
|
||||||
# Note: copyloopvar, intrange, modernize, perfsprint require Go 1.22+
|
# Note: copyloopvar, intrange, modernize, perfsprint require Go 1.22+
|
||||||
# They will be enabled when Go version constraint is lifted
|
# They will be enabled when Go version constraint is lifted.
|
||||||
|
|
||||||
settings:
|
settings:
|
||||||
depguard:
|
depguard:
|
||||||
@@ -61,6 +72,8 @@ linters:
|
|||||||
desc: Deprecated since Go 1.16. Use io and os packages instead.
|
desc: Deprecated since Go 1.16. Use io and os packages instead.
|
||||||
- pkg: "github.com/instana/testify"
|
- pkg: "github.com/instana/testify"
|
||||||
desc: Use github.com/stretchr/testify instead.
|
desc: Use github.com/stretchr/testify instead.
|
||||||
|
exhaustive:
|
||||||
|
default-signifies-exhaustive: true
|
||||||
dupl:
|
dupl:
|
||||||
threshold: 100
|
threshold: 100
|
||||||
funlen:
|
funlen:
|
||||||
@@ -82,17 +95,15 @@ linters:
|
|||||||
disabled-checks:
|
disabled-checks:
|
||||||
- dupImport
|
- dupImport
|
||||||
- hugeParam
|
- hugeParam
|
||||||
- rangeValCopy
|
- rangeValCopy # keychainbreaker structs are large by design
|
||||||
- ifElseChain
|
- unnamedResult # crypto functions returning (key, iv) are clear without names
|
||||||
- octalLiteral
|
|
||||||
- whyNoLint
|
- whyNoLint
|
||||||
- singleCaseSwitch
|
|
||||||
- exitAfterDefer
|
|
||||||
- commentedOutCode
|
|
||||||
lll:
|
lll:
|
||||||
line-length: 140
|
line-length: 140
|
||||||
gocognit:
|
gocognit:
|
||||||
min-complexity: 30
|
min-complexity: 30
|
||||||
|
nestif:
|
||||||
|
min-complexity: 5
|
||||||
godox:
|
godox:
|
||||||
keywords:
|
keywords:
|
||||||
- FIXME
|
- FIXME
|
||||||
@@ -103,17 +114,17 @@ linters:
|
|||||||
asserts: false
|
asserts: false
|
||||||
gosec:
|
gosec:
|
||||||
excludes:
|
excludes:
|
||||||
- G101
|
- G101 # hardcoded credentials — false positives on const names
|
||||||
- G104
|
- G115 # integer overflow on conversion — false positives on safe narrowing
|
||||||
- G304
|
- G117 # struct field matches secret pattern — false positive on Password fields
|
||||||
- G401
|
- G204 # exec.Command with variable — required for macOS `security` command
|
||||||
- G405
|
- G304 # file inclusion via variable — required for dynamic browser paths
|
||||||
- G501
|
- G401 # weak crypto SHA1 — required for Chromium PBKDF2 key derivation
|
||||||
- G502
|
- G402 # TLS MinVersion — not applicable (no TLS in this tool)
|
||||||
- G505
|
- G405 # weak crypto DES — required for Firefox 3DES decryption
|
||||||
- G115
|
- G501 # blocklisted import crypto/md5 — not used, keep for safety
|
||||||
- G117
|
- G502 # blocklisted import crypto/des — required for Firefox decryption
|
||||||
- G204
|
- G505 # blocklisted import crypto/sha1 — required for PBKDF2
|
||||||
errcheck:
|
errcheck:
|
||||||
check-type-assertions: true
|
check-type-assertions: true
|
||||||
exclude-functions:
|
exclude-functions:
|
||||||
@@ -127,22 +138,13 @@ linters:
|
|||||||
rules:
|
rules:
|
||||||
- name: indent-error-flow
|
- name: indent-error-flow
|
||||||
- name: unexported-return
|
- name: unexported-return
|
||||||
disabled: true
|
|
||||||
- name: unused-parameter
|
- name: unused-parameter
|
||||||
disabled: true
|
disabled: true
|
||||||
- name: package-comments
|
|
||||||
disabled: true
|
|
||||||
- name: exported
|
|
||||||
disabled: true
|
|
||||||
staticcheck:
|
staticcheck:
|
||||||
checks:
|
checks:
|
||||||
- "all"
|
- "all"
|
||||||
- "-ST1000"
|
- "-ST1000" # package comment — not a public library
|
||||||
- "-ST1003"
|
- "-ST1003" # naming convention — allow platform-specific names
|
||||||
- "-ST1016"
|
|
||||||
- "-ST1020"
|
|
||||||
- "-ST1021"
|
|
||||||
- "-ST1022"
|
|
||||||
|
|
||||||
exclusions:
|
exclusions:
|
||||||
presets:
|
presets:
|
||||||
@@ -157,7 +159,6 @@ linters:
|
|||||||
- funlen
|
- funlen
|
||||||
- gosec
|
- gosec
|
||||||
- errcheck
|
- errcheck
|
||||||
- testifylint
|
|
||||||
- lll
|
- lll
|
||||||
- source: "defer"
|
- source: "defer"
|
||||||
linters:
|
linters:
|
||||||
@@ -165,47 +166,12 @@ linters:
|
|||||||
- text: "SELECT"
|
- text: "SELECT"
|
||||||
linters:
|
linters:
|
||||||
- gosec
|
- gosec
|
||||||
# Temporary: known issues in pre-refactoring code (will be removed during refactoring)
|
|
||||||
- text: "result 0 .* is always nil"
|
|
||||||
linters:
|
|
||||||
- unparam
|
|
||||||
- text: "result 0 .* is never used"
|
|
||||||
linters:
|
|
||||||
- unparam
|
|
||||||
- path: "browser/firefox/firefox.go"
|
|
||||||
text: "field .* is unused"
|
|
||||||
linters:
|
|
||||||
- unused
|
|
||||||
- path: "browserdata/sessionstorage/"
|
|
||||||
text: "is unused"
|
|
||||||
linters:
|
|
||||||
- unused
|
|
||||||
- path: "cmd/hack-browser-data/main.go"
|
- path: "cmd/hack-browser-data/main.go"
|
||||||
linters:
|
linters:
|
||||||
- lll
|
- lll
|
||||||
# Temporary: pre-refactoring code issues (all will be rewritten)
|
|
||||||
- path: "browserdata/"
|
|
||||||
linters:
|
|
||||||
- dupl
|
|
||||||
- gochecknoinits
|
|
||||||
- goconst
|
|
||||||
- lll
|
|
||||||
- path: "browser/firefox/"
|
|
||||||
linters:
|
|
||||||
- gocritic
|
|
||||||
- path: "crypto/"
|
|
||||||
linters:
|
|
||||||
- gocritic
|
|
||||||
- path: "crypto/keyretriever/gcoredump_darwin.go"
|
- path: "crypto/keyretriever/gcoredump_darwin.go"
|
||||||
linters:
|
linters:
|
||||||
- gocognit
|
- gocognit
|
||||||
# Temporary: new v2 extract files have no callers until Phase 8 wiring
|
|
||||||
- path: "browser/chromium/(source|decrypt|extract_.*)\\.go"
|
|
||||||
linters:
|
|
||||||
- unused
|
|
||||||
- path: "browser/firefox/(source|extract_.*)\\.go"
|
|
||||||
linters:
|
|
||||||
- unused
|
|
||||||
|
|
||||||
formatters:
|
formatters:
|
||||||
enable:
|
enable:
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ func mkFile(t *testing.T, parts ...string) {
|
|||||||
|
|
||||||
func TestListBrowsers(t *testing.T) {
|
func TestListBrowsers(t *testing.T) {
|
||||||
list := ListBrowsers()
|
list := ListBrowsers()
|
||||||
assert.True(t, len(list) > 0)
|
assert.NotEmpty(t, list)
|
||||||
assert.True(t, sort.StringsAreSorted(list))
|
assert.True(t, sort.StringsAreSorted(list))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -399,7 +399,7 @@ func TestAcquireFiles(t *testing.T) {
|
|||||||
assert.Len(t, paths, len(cats))
|
assert.Len(t, paths, len(cats))
|
||||||
for _, p := range paths {
|
for _, p := range paths {
|
||||||
_, err := os.Stat(p)
|
_, err := os.Stat(p)
|
||||||
assert.NoError(t, err, "acquired file should exist")
|
require.NoError(t, err, "acquired file should exist")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -40,5 +40,5 @@ func TestExtractHistories_NullFields(t *testing.T) {
|
|||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
require.Len(t, got, 1)
|
require.Len(t, got, 1)
|
||||||
assert.Equal(t, "https://null.test", got[0].URL)
|
assert.Equal(t, "https://null.test", got[0].URL)
|
||||||
assert.Equal(t, "", got[0].Title)
|
assert.Empty(t, got[0].Title)
|
||||||
}
|
}
|
||||||
|
|||||||
+23
-22
@@ -7,6 +7,7 @@ import (
|
|||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
|
"github.com/stretchr/testify/require"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
@@ -74,14 +75,14 @@ var (
|
|||||||
func TestNewASN1PBE(t *testing.T) {
|
func TestNewASN1PBE(t *testing.T) {
|
||||||
for _, tc := range nssPBETestCases {
|
for _, tc := range nssPBETestCases {
|
||||||
nssRaw, err := hex.DecodeString(tc.RawHexPBE)
|
nssRaw, err := hex.DecodeString(tc.RawHexPBE)
|
||||||
assert.Equal(t, nil, err)
|
require.NoError(t, err)
|
||||||
pbe, err := NewASN1PBE(nssRaw)
|
pbe, err := NewASN1PBE(nssRaw)
|
||||||
assert.Equal(t, nil, err)
|
require.NoError(t, err)
|
||||||
nssPBETC, ok := pbe.(nssPBE)
|
nssPBETC, ok := pbe.(nssPBE)
|
||||||
assert.Equal(t, true, ok)
|
assert.True(t, ok)
|
||||||
assert.Equal(t, nssPBETC.Encrypted, tc.Encrypted)
|
assert.Equal(t, nssPBETC.Encrypted, tc.Encrypted)
|
||||||
assert.Equal(t, nssPBETC.AlgoAttr.SaltAttr.EntrySalt, tc.GlobalSalt)
|
assert.Equal(t, nssPBETC.AlgoAttr.SaltAttr.EntrySalt, tc.GlobalSalt)
|
||||||
assert.Equal(t, nssPBETC.AlgoAttr.SaltAttr.Len, 20)
|
assert.Equal(t, 20, nssPBETC.AlgoAttr.SaltAttr.Len)
|
||||||
assert.Equal(t, nssPBETC.AlgoAttr.ObjectIdentifier, tc.ObjectIdentifier)
|
assert.Equal(t, nssPBETC.AlgoAttr.ObjectIdentifier, tc.ObjectIdentifier)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -108,8 +109,8 @@ func TestNssPBE_Encrypt(t *testing.T) {
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
encrypted, err := nssPBETC.Encrypt(tc.GlobalSalt, tc.Plaintext)
|
encrypted, err := nssPBETC.Encrypt(tc.GlobalSalt, tc.Plaintext)
|
||||||
assert.Equal(t, nil, err)
|
require.NoError(t, err)
|
||||||
assert.Equal(t, true, len(encrypted) > 0)
|
assert.NotEmpty(t, encrypted)
|
||||||
assert.Equal(t, nssPBETC.Encrypted, encrypted)
|
assert.Equal(t, nssPBETC.Encrypted, encrypted)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -136,8 +137,8 @@ func TestNssPBE_Decrypt(t *testing.T) {
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
decrypted, err := nssPBETC.Decrypt(tc.GlobalSalt)
|
decrypted, err := nssPBETC.Decrypt(tc.GlobalSalt)
|
||||||
assert.Equal(t, nil, err)
|
require.NoError(t, err)
|
||||||
assert.Equal(t, true, len(decrypted) > 0)
|
assert.NotEmpty(t, decrypted)
|
||||||
assert.Equal(t, pbePlaintext, decrypted)
|
assert.Equal(t, pbePlaintext, decrypted)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -145,11 +146,11 @@ func TestNssPBE_Decrypt(t *testing.T) {
|
|||||||
func TestNewASN1PBE_MetaPBE(t *testing.T) {
|
func TestNewASN1PBE_MetaPBE(t *testing.T) {
|
||||||
for _, tc := range metaPBETestCases {
|
for _, tc := range metaPBETestCases {
|
||||||
metaRaw, err := hex.DecodeString(tc.RawHexPBE)
|
metaRaw, err := hex.DecodeString(tc.RawHexPBE)
|
||||||
assert.Equal(t, nil, err)
|
require.NoError(t, err)
|
||||||
pbe, err := NewASN1PBE(metaRaw)
|
pbe, err := NewASN1PBE(metaRaw)
|
||||||
assert.Equal(t, nil, err)
|
require.NoError(t, err)
|
||||||
metaPBETC, ok := pbe.(metaPBE)
|
metaPBETC, ok := pbe.(metaPBE)
|
||||||
assert.Equal(t, true, ok)
|
assert.True(t, ok)
|
||||||
assert.Equal(t, metaPBETC.Encrypted, tc.Encrypted)
|
assert.Equal(t, metaPBETC.Encrypted, tc.Encrypted)
|
||||||
assert.Equal(t, metaPBETC.AlgoAttr.Data.IVData.IV, tc.IV)
|
assert.Equal(t, metaPBETC.AlgoAttr.Data.IVData.IV, tc.IV)
|
||||||
assert.Equal(t, metaPBETC.AlgoAttr.Data.IVData.ObjectIdentifier, objWithSHA256AndAES)
|
assert.Equal(t, metaPBETC.AlgoAttr.Data.IVData.ObjectIdentifier, objWithSHA256AndAES)
|
||||||
@@ -193,8 +194,8 @@ func TestMetaPBE_Encrypt(t *testing.T) {
|
|||||||
Encrypted: tc.Encrypted,
|
Encrypted: tc.Encrypted,
|
||||||
}
|
}
|
||||||
encrypted, err := metaPBETC.Encrypt(tc.GlobalSalt, tc.Plaintext)
|
encrypted, err := metaPBETC.Encrypt(tc.GlobalSalt, tc.Plaintext)
|
||||||
assert.Equal(t, nil, err)
|
require.NoError(t, err)
|
||||||
assert.Equal(t, true, len(encrypted) > 0)
|
assert.NotEmpty(t, encrypted)
|
||||||
assert.Equal(t, metaPBETC.Encrypted, encrypted)
|
assert.Equal(t, metaPBETC.Encrypted, encrypted)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -236,8 +237,8 @@ func TestMetaPBE_Decrypt(t *testing.T) {
|
|||||||
Encrypted: tc.Encrypted,
|
Encrypted: tc.Encrypted,
|
||||||
}
|
}
|
||||||
decrypted, err := metaPBETC.Decrypt(tc.GlobalSalt)
|
decrypted, err := metaPBETC.Decrypt(tc.GlobalSalt)
|
||||||
assert.Equal(t, nil, err)
|
require.NoError(t, err)
|
||||||
assert.Equal(t, true, len(decrypted) > 0)
|
assert.NotEmpty(t, decrypted)
|
||||||
assert.Equal(t, pbePlaintext, decrypted)
|
assert.Equal(t, pbePlaintext, decrypted)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -245,11 +246,11 @@ func TestMetaPBE_Decrypt(t *testing.T) {
|
|||||||
func TestNewASN1PBE_LoginPBE(t *testing.T) {
|
func TestNewASN1PBE_LoginPBE(t *testing.T) {
|
||||||
for _, tc := range loginPBETestCases {
|
for _, tc := range loginPBETestCases {
|
||||||
loginRaw, err := hex.DecodeString(tc.RawHexPBE)
|
loginRaw, err := hex.DecodeString(tc.RawHexPBE)
|
||||||
assert.Equal(t, nil, err)
|
require.NoError(t, err)
|
||||||
pbe, err := NewASN1PBE(loginRaw)
|
pbe, err := NewASN1PBE(loginRaw)
|
||||||
assert.Equal(t, nil, err)
|
require.NoError(t, err)
|
||||||
loginPBETC, ok := pbe.(loginPBE)
|
loginPBETC, ok := pbe.(loginPBE)
|
||||||
assert.Equal(t, true, ok)
|
assert.True(t, ok)
|
||||||
assert.Equal(t, loginPBETC.Encrypted, tc.Encrypted)
|
assert.Equal(t, loginPBETC.Encrypted, tc.Encrypted)
|
||||||
assert.Equal(t, loginPBETC.Data.IV, tc.IV)
|
assert.Equal(t, loginPBETC.Data.IV, tc.IV)
|
||||||
assert.Equal(t, loginPBETC.Data.ObjectIdentifier, objWithMD5AndDESCBC)
|
assert.Equal(t, loginPBETC.Data.ObjectIdentifier, objWithMD5AndDESCBC)
|
||||||
@@ -270,8 +271,8 @@ func TestLoginPBE_Encrypt(t *testing.T) {
|
|||||||
Encrypted: tc.Encrypted,
|
Encrypted: tc.Encrypted,
|
||||||
}
|
}
|
||||||
encrypted, err := loginPBETC.Encrypt(tc.GlobalSalt, plainText)
|
encrypted, err := loginPBETC.Encrypt(tc.GlobalSalt, plainText)
|
||||||
assert.Equal(t, nil, err)
|
require.NoError(t, err)
|
||||||
assert.Equal(t, true, len(encrypted) > 0)
|
assert.NotEmpty(t, encrypted)
|
||||||
assert.Equal(t, loginPBETC.Encrypted, encrypted)
|
assert.Equal(t, loginPBETC.Encrypted, encrypted)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -290,8 +291,8 @@ func TestLoginPBE_Decrypt(t *testing.T) {
|
|||||||
Encrypted: tc.Encrypted,
|
Encrypted: tc.Encrypted,
|
||||||
}
|
}
|
||||||
decrypted, err := loginPBETC.Decrypt(tc.GlobalSalt)
|
decrypted, err := loginPBETC.Decrypt(tc.GlobalSalt)
|
||||||
assert.Equal(t, nil, err)
|
require.NoError(t, err)
|
||||||
assert.Equal(t, true, len(decrypted) > 0)
|
assert.NotEmpty(t, decrypted)
|
||||||
assert.Equal(t, pbePlaintext, decrypted)
|
assert.Equal(t, pbePlaintext, decrypted)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+13
-12
@@ -8,6 +8,7 @@ import (
|
|||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
|
"github.com/stretchr/testify/require"
|
||||||
)
|
)
|
||||||
|
|
||||||
const baseKey = "moond4rk"
|
const baseKey = "moond4rk"
|
||||||
@@ -28,45 +29,45 @@ var (
|
|||||||
|
|
||||||
func TestAES128CBCEncrypt(t *testing.T) {
|
func TestAES128CBCEncrypt(t *testing.T) {
|
||||||
encrypted, err := AES128CBCEncrypt(aesKey, aesIV, plainText)
|
encrypted, err := AES128CBCEncrypt(aesKey, aesIV, plainText)
|
||||||
assert.Equal(t, nil, err)
|
require.NoError(t, err)
|
||||||
assert.Equal(t, true, len(encrypted) > 0)
|
assert.NotEmpty(t, encrypted)
|
||||||
assert.Equal(t, aes128Ciphertext, fmt.Sprintf("%x", encrypted))
|
assert.Equal(t, aes128Ciphertext, fmt.Sprintf("%x", encrypted))
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestAES128CBCDecrypt(t *testing.T) {
|
func TestAES128CBCDecrypt(t *testing.T) {
|
||||||
ciphertext, _ := hex.DecodeString(aes128Ciphertext)
|
ciphertext, _ := hex.DecodeString(aes128Ciphertext)
|
||||||
decrypted, err := AES128CBCDecrypt(aesKey, aesIV, ciphertext)
|
decrypted, err := AES128CBCDecrypt(aesKey, aesIV, ciphertext)
|
||||||
assert.Equal(t, nil, err)
|
require.NoError(t, err)
|
||||||
assert.Equal(t, true, len(decrypted) > 0)
|
assert.NotEmpty(t, decrypted)
|
||||||
assert.Equal(t, plainText, decrypted)
|
assert.Equal(t, plainText, decrypted)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestDES3Encrypt(t *testing.T) {
|
func TestDES3Encrypt(t *testing.T) {
|
||||||
encrypted, err := DES3Encrypt(des3Key, des3IV, plainText)
|
encrypted, err := DES3Encrypt(des3Key, des3IV, plainText)
|
||||||
assert.Equal(t, nil, err)
|
require.NoError(t, err)
|
||||||
assert.Equal(t, true, len(encrypted) > 0)
|
assert.NotEmpty(t, encrypted)
|
||||||
assert.Equal(t, des3Ciphertext, fmt.Sprintf("%x", encrypted))
|
assert.Equal(t, des3Ciphertext, fmt.Sprintf("%x", encrypted))
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestDES3Decrypt(t *testing.T) {
|
func TestDES3Decrypt(t *testing.T) {
|
||||||
ciphertext, _ := hex.DecodeString(des3Ciphertext)
|
ciphertext, _ := hex.DecodeString(des3Ciphertext)
|
||||||
decrypted, err := DES3Decrypt(des3Key, des3IV, ciphertext)
|
decrypted, err := DES3Decrypt(des3Key, des3IV, ciphertext)
|
||||||
assert.Equal(t, nil, err)
|
require.NoError(t, err)
|
||||||
assert.Equal(t, true, len(decrypted) > 0)
|
assert.NotEmpty(t, decrypted)
|
||||||
assert.Equal(t, plainText, decrypted)
|
assert.Equal(t, plainText, decrypted)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestAESGCMEncrypt(t *testing.T) {
|
func TestAESGCMEncrypt(t *testing.T) {
|
||||||
encrypted, err := AESGCMEncrypt(aesKey, aesGCMNonce, plainText)
|
encrypted, err := AESGCMEncrypt(aesKey, aesGCMNonce, plainText)
|
||||||
assert.Equal(t, nil, err)
|
require.NoError(t, err)
|
||||||
assert.Equal(t, true, len(encrypted) > 0)
|
assert.NotEmpty(t, encrypted)
|
||||||
assert.Equal(t, aesGCMCiphertext, fmt.Sprintf("%x", encrypted))
|
assert.Equal(t, aesGCMCiphertext, fmt.Sprintf("%x", encrypted))
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestAESGCMDecrypt(t *testing.T) {
|
func TestAESGCMDecrypt(t *testing.T) {
|
||||||
ciphertext, _ := hex.DecodeString(aesGCMCiphertext)
|
ciphertext, _ := hex.DecodeString(aesGCMCiphertext)
|
||||||
decrypted, err := AESGCMDecrypt(aesKey, aesGCMNonce, ciphertext)
|
decrypted, err := AESGCMDecrypt(aesKey, aesGCMNonce, ciphertext)
|
||||||
assert.Equal(t, nil, err)
|
require.NoError(t, err)
|
||||||
assert.Equal(t, true, len(decrypted) > 0)
|
assert.NotEmpty(t, decrypted)
|
||||||
assert.Equal(t, plainText, decrypted)
|
assert.Equal(t, plainText, decrypted)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -43,7 +43,7 @@ func TestChainRetriever_AllFail(t *testing.T) {
|
|||||||
&mockRetriever{err: errors.New("second failed")},
|
&mockRetriever{err: errors.New("second failed")},
|
||||||
)
|
)
|
||||||
key, err := chain.RetrieveKey("Chrome", "")
|
key, err := chain.RetrieveKey("Chrome", "")
|
||||||
assert.Error(t, err)
|
require.Error(t, err)
|
||||||
assert.Nil(t, key)
|
assert.Nil(t, key)
|
||||||
assert.Contains(t, err.Error(), "all retrievers failed")
|
assert.Contains(t, err.Error(), "all retrievers failed")
|
||||||
assert.Contains(t, err.Error(), "first failed")
|
assert.Contains(t, err.Error(), "first failed")
|
||||||
@@ -64,6 +64,6 @@ func TestChainRetriever_SkipEmptyKey(t *testing.T) {
|
|||||||
func TestChainRetriever_Empty(t *testing.T) {
|
func TestChainRetriever_Empty(t *testing.T) {
|
||||||
chain := NewChain()
|
chain := NewChain()
|
||||||
key, err := chain.RetrieveKey("Chrome", "")
|
key, err := chain.RetrieveKey("Chrome", "")
|
||||||
assert.Error(t, err)
|
require.Error(t, err)
|
||||||
assert.Nil(t, key)
|
assert.Nil(t, key)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -25,12 +25,12 @@ func TestCopyLocked_ExclusiveLock(t *testing.T) {
|
|||||||
|
|
||||||
// Normal copy should fail
|
// Normal copy should fail
|
||||||
err := copyFile(src, filepath.Join(dir, "normal_copy.db"))
|
err := copyFile(src, filepath.Join(dir, "normal_copy.db"))
|
||||||
assert.Error(t, err, "normal copy should fail on exclusively locked file")
|
require.Error(t, err, "normal copy should fail on exclusively locked file")
|
||||||
|
|
||||||
// copyLocked should succeed via DuplicateHandle + FileMapping
|
// copyLocked should succeed via DuplicateHandle + FileMapping
|
||||||
lockedDst := filepath.Join(dir, "locked_copy.db")
|
lockedDst := filepath.Join(dir, "locked_copy.db")
|
||||||
err = copyLocked(src, lockedDst)
|
err = copyLocked(src, lockedDst)
|
||||||
assert.NoError(t, err, "copyLocked should bypass exclusive lock")
|
require.NoError(t, err, "copyLocked should bypass exclusive lock")
|
||||||
|
|
||||||
copied, err := os.ReadFile(lockedDst)
|
copied, err := os.ReadFile(lockedDst)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
@@ -62,7 +62,7 @@ func TestCopyLocked_WriteThenRead(t *testing.T) {
|
|||||||
// copyLocked should read the full content including appended data
|
// copyLocked should read the full content including appended data
|
||||||
lockedDst := filepath.Join(dir, "modified_copy.db")
|
lockedDst := filepath.Join(dir, "modified_copy.db")
|
||||||
copyErr := copyLocked(src, lockedDst)
|
copyErr := copyLocked(src, lockedDst)
|
||||||
assert.NoError(t, copyErr)
|
require.NoError(t, copyErr)
|
||||||
|
|
||||||
copied, err := os.ReadFile(lockedDst)
|
copied, err := os.ReadFile(lockedDst)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
@@ -86,17 +86,17 @@ func TestCopyLocked_LargeFile(t *testing.T) {
|
|||||||
|
|
||||||
lockedDst := filepath.Join(dir, "large_copy.db")
|
lockedDst := filepath.Join(dir, "large_copy.db")
|
||||||
err := copyLocked(src, lockedDst)
|
err := copyLocked(src, lockedDst)
|
||||||
assert.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
copied, err := os.ReadFile(lockedDst)
|
copied, err := os.ReadFile(lockedDst)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
assert.Equal(t, len(data), len(copied), "file sizes should match")
|
assert.Len(t, copied, len(data), "file sizes should match")
|
||||||
assert.True(t, bytes.Equal(data, copied), "file content should match byte-for-byte")
|
assert.True(t, bytes.Equal(data, copied), "file content should match byte-for-byte")
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestCopyLocked_FileNotFound(t *testing.T) {
|
func TestCopyLocked_FileNotFound(t *testing.T) {
|
||||||
err := copyLocked("/nonexistent/file.db", filepath.Join(t.TempDir(), "dst.db"))
|
err := copyLocked("/nonexistent/file.db", filepath.Join(t.TempDir(), "dst.db"))
|
||||||
assert.Error(t, err)
|
require.Error(t, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestAcquire_FallbackToLocked(t *testing.T) {
|
func TestAcquire_FallbackToLocked(t *testing.T) {
|
||||||
@@ -115,7 +115,7 @@ func TestAcquire_FallbackToLocked(t *testing.T) {
|
|||||||
|
|
||||||
dst := filepath.Join(session.TempDir(), "cookies.db")
|
dst := filepath.Join(session.TempDir(), "cookies.db")
|
||||||
err = session.Acquire(src, dst, false)
|
err = session.Acquire(src, dst, false)
|
||||||
assert.NoError(t, err, "Acquire should succeed via locked fallback")
|
require.NoError(t, err, "Acquire should succeed via locked fallback")
|
||||||
|
|
||||||
copied, err := os.ReadFile(dst)
|
copied, err := os.ReadFile(dst)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
@@ -136,7 +136,7 @@ func TestAcquire_NormalCopyWhenNotLocked(t *testing.T) {
|
|||||||
|
|
||||||
dst := filepath.Join(session.TempDir(), "unlocked.db")
|
dst := filepath.Join(session.TempDir(), "unlocked.db")
|
||||||
err = session.Acquire(src, dst, false)
|
err = session.Acquire(src, dst, false)
|
||||||
assert.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
copied, err := os.ReadFile(dst)
|
copied, err := os.ReadFile(dst)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|||||||
@@ -42,7 +42,7 @@ func TestSession_Acquire_File(t *testing.T) {
|
|||||||
// Acquire it
|
// Acquire it
|
||||||
dst := filepath.Join(s.TempDir(), "Login Data")
|
dst := filepath.Join(s.TempDir(), "Login Data")
|
||||||
err = s.Acquire(srcFile, dst, false)
|
err = s.Acquire(srcFile, dst, false)
|
||||||
assert.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
// Verify copy
|
// Verify copy
|
||||||
data, err := os.ReadFile(dst)
|
data, err := os.ReadFile(dst)
|
||||||
@@ -63,7 +63,7 @@ func TestSession_Acquire_WAL(t *testing.T) {
|
|||||||
|
|
||||||
dst := filepath.Join(s.TempDir(), "Cookies")
|
dst := filepath.Join(s.TempDir(), "Cookies")
|
||||||
err = s.Acquire(srcFile, dst, false)
|
err = s.Acquire(srcFile, dst, false)
|
||||||
assert.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
// Main file copied
|
// Main file copied
|
||||||
assert.FileExists(t, dst)
|
assert.FileExists(t, dst)
|
||||||
@@ -85,7 +85,7 @@ func TestSession_Acquire_Dir(t *testing.T) {
|
|||||||
|
|
||||||
dst := filepath.Join(s.TempDir(), "leveldb")
|
dst := filepath.Join(s.TempDir(), "leveldb")
|
||||||
err = s.Acquire(srcDir, dst, true)
|
err = s.Acquire(srcDir, dst, true)
|
||||||
assert.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
// Data file copied
|
// Data file copied
|
||||||
assert.FileExists(t, filepath.Join(dst, "000001.ldb"))
|
assert.FileExists(t, filepath.Join(dst, "000001.ldb"))
|
||||||
@@ -99,5 +99,5 @@ func TestSession_Acquire_NotFound(t *testing.T) {
|
|||||||
|
|
||||||
dst := filepath.Join(s.TempDir(), "nope")
|
dst := filepath.Join(s.TempDir(), "nope")
|
||||||
err = s.Acquire("/nonexistent/file", dst, false)
|
err = s.Acquire("/nonexistent/file", dst, false)
|
||||||
assert.Error(t, err)
|
require.Error(t, err)
|
||||||
}
|
}
|
||||||
|
|||||||
+15
-5
@@ -7,17 +7,27 @@ import (
|
|||||||
"github.com/moond4rk/hackbrowserdata/types"
|
"github.com/moond4rk/hackbrowserdata/types"
|
||||||
)
|
)
|
||||||
|
|
||||||
type cookieEditorFormatter struct{}
|
// cookieEditorFormatter outputs cookies in the CookieEditor browser extension
|
||||||
|
// format. Non-cookie categories fall back to standard JSON output.
|
||||||
|
type cookieEditorFormatter struct {
|
||||||
|
fallback *jsonFormatter
|
||||||
|
}
|
||||||
|
|
||||||
func (f *cookieEditorFormatter) ext() string { return "json" }
|
func (f *cookieEditorFormatter) ext() string { return "json" }
|
||||||
|
|
||||||
func (f *cookieEditorFormatter) format(w io.Writer, rows []row) error {
|
func (f *cookieEditorFormatter) format(w io.Writer, rows []row) error {
|
||||||
|
if len(rows) == 0 {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
// aggregate() guarantees all rows in a batch share the same type;
|
||||||
|
// check the first row to decide the format.
|
||||||
|
if _, ok := rows[0].entry.(types.CookieEntry); !ok {
|
||||||
|
return f.fallback.format(w, rows)
|
||||||
|
}
|
||||||
|
|
||||||
entries := make([]cookieEditorEntry, 0, len(rows))
|
entries := make([]cookieEditorEntry, 0, len(rows))
|
||||||
for _, r := range rows {
|
for _, r := range rows {
|
||||||
c, ok := r.entry.(types.CookieEntry)
|
c, _ := r.entry.(types.CookieEntry)
|
||||||
if !ok {
|
|
||||||
return nil // not cookies, skip
|
|
||||||
}
|
|
||||||
var expDate float64
|
var expDate float64
|
||||||
if !c.ExpireAt.IsZero() {
|
if !c.ExpireAt.IsZero() {
|
||||||
expDate = float64(c.ExpireAt.Unix())
|
expDate = float64(c.ExpireAt.Unix())
|
||||||
|
|||||||
+1
-1
@@ -18,7 +18,7 @@ func newFormatter(name string) (formatter, error) {
|
|||||||
case "json":
|
case "json":
|
||||||
return &jsonFormatter{}, nil
|
return &jsonFormatter{}, nil
|
||||||
case "cookie-editor":
|
case "cookie-editor":
|
||||||
return &cookieEditorFormatter{}, nil
|
return &cookieEditorFormatter{fallback: &jsonFormatter{}}, nil
|
||||||
default:
|
default:
|
||||||
return nil, fmt.Errorf("unsupported format: %s", name)
|
return nil, fmt.Errorf("unsupported format: %s", name)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -65,10 +65,10 @@ func TestNew(t *testing.T) {
|
|||||||
t.Run(tt.format, func(t *testing.T) {
|
t.Run(tt.format, func(t *testing.T) {
|
||||||
out, err := NewWriter(t.TempDir(), tt.format)
|
out, err := NewWriter(t.TempDir(), tt.format)
|
||||||
if tt.wantErr {
|
if tt.wantErr {
|
||||||
assert.Error(t, err)
|
require.Error(t, err)
|
||||||
assert.Nil(t, out)
|
assert.Nil(t, out)
|
||||||
} else {
|
} else {
|
||||||
assert.NoError(t, err)
|
require.NoError(t, err)
|
||||||
assert.NotNil(t, out)
|
assert.NotNil(t, out)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
@@ -142,7 +142,7 @@ func TestWrite_CSV_UTF8BOM(t *testing.T) {
|
|||||||
|
|
||||||
raw, err := os.ReadFile(filepath.Join(dir, "password.csv"))
|
raw, err := os.ReadFile(filepath.Join(dir, "password.csv"))
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
require.True(t, len(raw) >= 3)
|
require.GreaterOrEqual(t, len(raw), 3)
|
||||||
assert.Equal(t, utf8BOM, raw[:3], "CSV should start with UTF-8 BOM")
|
assert.Equal(t, utf8BOM, raw[:3], "CSV should start with UTF-8 BOM")
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -249,7 +249,7 @@ func TestWrite_CookieEditor(t *testing.T) {
|
|||||||
}, entries[0])
|
}, entries[0])
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestWrite_CookieEditor_SkipsNonCookie(t *testing.T) {
|
func TestWrite_CookieEditor_FallbackJSON(t *testing.T) {
|
||||||
dir := t.TempDir()
|
dir := t.TempDir()
|
||||||
out, err := NewWriter(dir, "cookie-editor")
|
out, err := NewWriter(dir, "cookie-editor")
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
@@ -258,9 +258,9 @@ func TestWrite_CookieEditor_SkipsNonCookie(t *testing.T) {
|
|||||||
})
|
})
|
||||||
require.NoError(t, out.Write())
|
require.NoError(t, out.Write())
|
||||||
|
|
||||||
// password file should not be created (cookie-editor only exports cookies)
|
// non-cookie categories fall back to standard JSON format
|
||||||
_, err = os.Stat(filepath.Join(dir, "password.json"))
|
_, err = os.Stat(filepath.Join(dir, "password.json"))
|
||||||
assert.True(t, os.IsNotExist(err))
|
assert.False(t, os.IsNotExist(err), "password.json should be created via JSON fallback")
|
||||||
}
|
}
|
||||||
|
|
||||||
// --- File creation ---
|
// --- File creation ---
|
||||||
|
|||||||
@@ -29,7 +29,7 @@ func TestCompressDir(t *testing.T) {
|
|||||||
defer os.RemoveAll(tempDir)
|
defer os.RemoveAll(tempDir)
|
||||||
|
|
||||||
err := CompressDir(tempDir)
|
err := CompressDir(tempDir)
|
||||||
assert.NoError(t, err, "compressDir should not return an error")
|
require.NoError(t, err, "compressDir should not return an error")
|
||||||
|
|
||||||
// Check if the zip file exists
|
// Check if the zip file exists
|
||||||
zipFile := filepath.Join(tempDir, filepath.Base(tempDir)+".zip")
|
zipFile := filepath.Join(tempDir, filepath.Base(tempDir)+".zip")
|
||||||
@@ -38,7 +38,7 @@ func TestCompressDir(t *testing.T) {
|
|||||||
|
|
||||||
t.Run("Directory Does Not Exist", func(t *testing.T) {
|
t.Run("Directory Does Not Exist", func(t *testing.T) {
|
||||||
err := CompressDir("/path/to/nonexistent/directory")
|
err := CompressDir("/path/to/nonexistent/directory")
|
||||||
assert.Error(t, err, "should return an error for non-existent directory")
|
require.Error(t, err, "should return an error for non-existent directory")
|
||||||
})
|
})
|
||||||
|
|
||||||
t.Run("Empty Directory", func(t *testing.T) {
|
t.Run("Empty Directory", func(t *testing.T) {
|
||||||
@@ -47,6 +47,6 @@ func TestCompressDir(t *testing.T) {
|
|||||||
defer os.RemoveAll(tempDir)
|
defer os.RemoveAll(tempDir)
|
||||||
|
|
||||||
err = CompressDir(tempDir)
|
err = CompressDir(tempDir)
|
||||||
assert.Error(t, err, "should return an error for an empty directory")
|
require.Error(t, err, "should return an error for an empty directory")
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -34,7 +34,7 @@ func TestQuerySQLite(t *testing.T) {
|
|||||||
return nil
|
return nil
|
||||||
})
|
})
|
||||||
|
|
||||||
assert.NoError(t, err)
|
require.NoError(t, err)
|
||||||
assert.Equal(t, []string{"alpha", "beta", "gamma"}, names)
|
assert.Equal(t, []string{"alpha", "beta", "gamma"}, names)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -59,7 +59,7 @@ func TestQuerySQLite_JournalOff(t *testing.T) {
|
|||||||
values = append(values, v)
|
values = append(values, v)
|
||||||
return nil
|
return nil
|
||||||
})
|
})
|
||||||
assert.NoError(t, err)
|
require.NoError(t, err)
|
||||||
assert.Equal(t, []string{"ok"}, values)
|
assert.Equal(t, []string{"ok"}, values)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -67,7 +67,7 @@ func TestQuerySQLite_FileNotFound(t *testing.T) {
|
|||||||
err := QuerySQLite("/nonexistent/path.db", false, "SELECT 1", func(rows *sql.Rows) error {
|
err := QuerySQLite("/nonexistent/path.db", false, "SELECT 1", func(rows *sql.Rows) error {
|
||||||
return nil
|
return nil
|
||||||
})
|
})
|
||||||
assert.Error(t, err)
|
require.Error(t, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestQuerySQLite_BadQuery(t *testing.T) {
|
func TestQuerySQLite_BadQuery(t *testing.T) {
|
||||||
@@ -83,7 +83,7 @@ func TestQuerySQLite_BadQuery(t *testing.T) {
|
|||||||
err = QuerySQLite(dbPath, false, "SELECT nonexistent FROM t", func(rows *sql.Rows) error {
|
err = QuerySQLite(dbPath, false, "SELECT nonexistent FROM t", func(rows *sql.Rows) error {
|
||||||
return nil
|
return nil
|
||||||
})
|
})
|
||||||
assert.Error(t, err)
|
require.Error(t, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestQueryRows(t *testing.T) {
|
func TestQueryRows(t *testing.T) {
|
||||||
@@ -110,7 +110,7 @@ func TestQueryRows(t *testing.T) {
|
|||||||
return u, err
|
return u, err
|
||||||
})
|
})
|
||||||
|
|
||||||
assert.NoError(t, err)
|
require.NoError(t, err)
|
||||||
assert.Equal(t, []user{{"alice", 30}, {"bob", 25}}, users)
|
assert.Equal(t, []user{{"alice", 30}, {"bob", 25}}, users)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -133,6 +133,6 @@ func TestQueryRows_Empty(t *testing.T) {
|
|||||||
return v, nil
|
return v, nil
|
||||||
})
|
})
|
||||||
|
|
||||||
assert.NoError(t, err)
|
require.NoError(t, err)
|
||||||
assert.Nil(t, results)
|
assert.Nil(t, results)
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user