Comments (11)
Please try this branch and see if that helps: https://github.com/bodgit/sevenzip/tree/wrong-password
It introduces a new PasswordError
type that will be returned if the archive uses some sort of encryption method but the archive headers cannot be read. It wraps the real error that occurred, which will be whatever is emitted by the decompression libraries.
You can assert that the returned error includes this type using errors.As
.
Like with the 7z
utility, this error is a hint at best. There can be situations where if the archive is encrypted but corrupt, with the correct password you could still get an error saying the password is wrong if the corruption stops the archive headers from being read.
from sevenzip.
Can you merge master into this branch? I'm interested in having better password-error identification. My app supports 'trying' multiple passwords, and right now I just try the next password on any error. If the archive is not encrypted, it'd be nice to just not try anymore passwords.
from sevenzip.
When reading another password protected 7z file, I get lzma: unexpected chunk type
.
Test case to replicate it (added to the OP):
{
name: "password protected, wrong password, another error",
archiveBase64: "N3q8ryccAATmiIjWEAAAAAAAAABqAAAAAAAAAPj97y5WCxqWKbLj7vDaXAe/cLh2AQQGAAEJEAAHCwEAAiQG8QcBElMPRIjTr6dLKHHK30sEtwLboyEhAQABAAwMCAAICgH8UFzbAAAFARkBABETAHQAZQB4AHQALgB0AHgAdAAAABkAFAoBADbNXd0pr9gBFQYBACCApIEAAA==",
password: "not 'password'",
}
from sevenzip.
For context, in all cases, I create the 7z file with:
$ echo testing > text.txt
$ 7z a -ppassword password.7z text.txt
$ cat password.7z | base64 | pbcopy
from sevenzip.
So the way the encryption works on 7-zip archives is that it performs the usual compression (with LZMA, or any other algorithm for that matter) in one layer, producing a compressed stream of bytes, then it's wrapped by the layer that does the encryption, producing the encrypted (and compressed) stream of bytes. The encryption has no idea what the underlying compression format was.
So conversely when it comes to the decryption/decompression, the decryption layer doesn't know what the correct password is as it still produces a stream of bytes even with the wrong password, it's only when the decompression layer tries to interpret it that it won't be a valid LZMA stream and produces the error but it can't easily distinguish between a corrupt unencrypted archive and a valid encrypted archive with the wrong password set.
As you can see from your test cases, setting the password to a variety of different bad values results in different errors and that's purely down to the decrypted stream being "more or less wrong" when interpreted by the underlying LZMA library.
Checking with the 7z
utility, even it doesn't know 100% that the password is wrong, the error message is more a hint when the archive has encryption enabled, and that's probably the best I can do.
from sevenzip.
Good point. That also matches my experience.
I have another extractor implementation using 7z
utility, and I just interpret the hint (and exit code == 2) as password being wrong.
$ 7z x -pwrongpassword password.7z
7-Zip (z) 21.07 (arm64) : Copyright (c) 1999-2021 Igor Pavlov : 2021-12-26
64-bit arm_v:8 locale=en_US.UTF-8 Threads:8, ASM
Scanning the drive for archives:
1 file, 154 bytes (1 KiB)
Extracting archive: password.7z
--
Path = password.7z
Type = 7z
Physical Size = 154
Headers Size = 138
Method = LZMA2:12 7zAES
Solid = -
Blocks = 1
ERROR: Data Error in encrypted file. Wrong password? : text.txt
Sub items Errors: 1
Archives with Errors: 1
Sub items Errors: 1
I can do the same thing for this package, but there seems to be a lot of noise (different types of errors) that could be misinterpreted as password being wrong. If there were a way to know that an archive can't be decrypted, I would be happy with that too.
from sevenzip.
Thanks!
I couldn't get it to work. I'm still getting the lzma: unexpected chunk type
error.
// go.mod
github.com/bodgit/sevenzip v1.3.1-0.20220814220638-421188bed950
func TestSevenzipPasswordError(t *testing.T) {
passwordDot7z := `N3q8ryccAATLw8/pEAAAAAAAAABqAAAAAAAAAL5k3wUq4RlmRrx/qDeBDV2MzerKAQQGAAEJEAAHCwEAAiQG8QcBElMPbBOTnKWOQVr5GQ8zDSlIuSEhAQABAAwMCAAICgH8UFzbAAAFARkBABETAHQAZQB4AHQALgB0AHgAdAAAABkAFAoBAMcsnkBbsNgBFQYBACCApIEAAA==`
tests := []struct {
name string
archiveBase64 string
wantErr bool
password string
}{
{
name: "correct pass",
archiveBase64: passwordDot7z,
password: "password",
wantErr: false,
},
{
name: "wrong pass",
archiveBase64: passwordDot7z,
password: "notpassword",
wantErr: true, // fails with lzma: unexpected chunk type
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
f, size := readBase64(tt.archiveBase64)
ar, err := sevenzip.NewReaderWithPassword(f, size, tt.password)
assert.NoError(t, err) // should have failed here!!!!!
for _, it := range ar.File {
af, err := it.Open()
assert.NoError(t, err)
_, err = io.Copy(ioutil.Discard, af)
if tt.wantErr {
var pErr *sevenzip.PasswordError
assert.ErrorAs(t, err, &pErr)
} else {
assert.NoError(t, err)
}
}
})
}
}
func readBase64(encoded string) (io.ReaderAt, int64) {
decoded, err := base64.StdEncoding.DecodeString(encoded)
if err != nil {
panic(err)
}
return bytesAt{decoded}, int64(len(decoded))
}
type bytesAt struct {
b []byte
}
func (b bytesAt) ReadAt(p []byte, off int64) (n int, err error) {
if off >= int64(len(b.b)) {
return 0, io.EOF
}
n = copy(p, b.b[off:])
return
}
this outputs:
=== RUN TestSevenzipPasswordError
--- FAIL: TestSevenzipPasswordError (0.05s)
=== RUN TestSevenzipPasswordError/correct_pass
--- PASS: TestSevenzipPasswordError/correct_pass (0.03s)
=== RUN TestSevenzipPasswordError/wrong_pass
s7zipgo_test.go:109:
Error Trace: /path/to/s7zipgo_test.go:109
Error: Should be in error chain:
expected: %!q(**sevenzip.PasswordError=0x14000010048)
in chain: "lzma: unexpected chunk type"
Test: TestSevenzipPasswordError/wrong_pass
--- FAIL: TestSevenzipPasswordError/wrong_pass (0.03s)
from sevenzip.
I tried it again with fixtures t2.7z
and t3.7z
in the repo, they fail at the right place.
Line 135 in 421188b
ar, err := sevenzip.NewReaderWithPassword(f, size, tt.password)
// err is a PasswordError
The files I'm using don't fail while opening the archive, but when reading a file off of them.
For reference, version of 7z
utility I'm using:
> 7z
7-Zip (z) 21.07 (arm64) : Copyright (c) 1999-2021 Igor Pavlov : 2021-12-26
64-bit arm_v:8 locale=UTF-8 Threads:8, ASM
> brew info sevenzip
sevenzip: stable 22.01 (bottled)
7-Zip is a file archiver with a high compression ratio
https://7-zip.org
/opt/homebrew/Cellar/sevenzip/21.07 (3 files, 1.9MB) *
Poured from bottle on 2022-04-11 at 21:11:57
From: https://github.com/Homebrew/homebrew-core/blob/HEAD/Formula/sevenzip.rb
License: LGPL-2.1-or-later and BSD-3-Clause
==> Analytics
install: 5,285 (30 days), 12,444 (90 days), 25,508 (365 days)
install-on-request: 5,283 (30 days), 12,436 (90 days), 25,497 (365 days)
build-error: 7 (30 days)
from sevenzip.
So I think you've managed to create a 7-zip archive that doesn't encrypt the headers, (i.e. what files are in the archive and how big they are, etc.), but the files themselves are encrypted. This means you'll never know if the password is wrong until you try and extract a file, there's no way around that unfortunately.
If you create your archive with -mhe=on
added then it encrypts the headers as well, that's how the t2.7z
& t3.7z
were created.
from sevenzip.
(i.e. what files are in the archive and how big they are, etc.)
Yeah, it found it bizarre that I could read file names.
I understand the difference now. I was only adding -p$pass
flag to 7z
command. I can confirm that adding -mhe
flag does give the error.
I guess I can chalk up any error starting with lzma:
and newRangeDecoder:
to decryption failure, because they all come from lzma
library.
from sevenzip.
Not necessarily, it depends what compression algorithm is used. LZMA is the default algorithm so that's the most common but you can use other algorithms such as bzip2, deflate, etc. and then there are other ones that are really filters such as delta and BCJ2 which aim to rearrange the file contents in a way that makes them compress better, they can also be stacked/wrapped. In Golang terminology, think of it as a chain of one or more io.Reader
s.
I've added support for most of the common algorithms where there's either support in the standard library or an external library and at the moment my code just bubbles up whatever error the underlying library emits in the case of an error.
It might be an idea to wrap these in a generic ReadError
type which can optionally be wrapped with that PasswordError
in the event there's some encryption involved but it will involve a lot more changes than those I added for the case of the headers being encrypted.
from sevenzip.
Related Issues (20)
- runtime error: index out of range [0] with length 0 HOT 9
- "invalid memory address or nil pointer dereference" when opening 7z file HOT 1
- Errors are not accessible since they are private with a lower case
- Low performance of .7z files with password HOT 2
- Extract files from a self-extracting exe HOT 8
- panic: runtime error: index out of range HOT 2
- low performance for aes7z HOT 2
- warning: a function definition without a prototype is deprecated in all versions HOT 2
- 解带密码的提示 Failed to open file in archive: lzma: unsupported chunk header byte HOT 1
- How to extract HOT 1
- Return list of volume archive files. HOT 14
- seek over file in archive HOT 2
- Support BCJ method HOT 8
- Support PPC method
- Unable to decrypt 7-ZIP file with password (err: breader.ReadByte: no data!) HOT 1
- Unable to decrypt 7-ZIP file with password (err: breader.ReadByte: no data!) HOT 1
- sevenzip as a guide HOT 3
- Add support for reading self-extracting archives
- Empty File processing issue HOT 4
- Fail to read .exe in .7z HOT 2
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from sevenzip.