Test zip password correctness in vb.net
I want to test if a zip has a particular password in vb.net. How can I create a function like check_if_zip_pass(file, pass) As Boolean
?
I can't seem to find anything in the .net framework that does this already, unless I'm missing something incredibly obvious.
This method should NOT extract the files, only return True
if the a开发者_StackOverflowttempted pass is valid and False
if not.
Use a 3rd party library, like DotNetZip. Keep in mind that passwords in zipfiles are applied to entries, not to the entire zip file. So your test doesn't quite make sense.
One reason WinZip may refuse to unpack the zipfile is that the very first entry is protected with a password. It could be the case that only some entries are protected by password, and some are not. It could be that different passwords are used on different entries. You'll have to decide what you want to do about these possibilities.
One option is to suppose that only one password is used on any entries in the zipfile that are encrypted. (This is not required by the zip specification) In that case, below is some sample code to check the password. There is no way to check a password without doing the decryption. So this code decrypts and extracts into Stream.Null.
public bool CheckZipPassword(string filename, string password)
{
bool success = false;
try
{
using (ZipFile zip1 = ZipFile.Read(filename))
{
var bitBucket = System.IO.Stream.Null;
foreach (var e in zip1)
{
if (!e.IsDirectory && e.UsesEncryption)
{
e.ExtractWithPassword(bitBucket, password);
}
}
}
success = true;
}
catch(Ionic.Zip.BadPasswordException) { }
return success;
}
Whoops! I think in C#. In VB.NET this would be:
Public Function CheckZipPassword(filename As String, password As String) As System.Boolean
Dim success As System.Boolean = False
Try
Using zip1 As ZipFile = ZipFile.Read(filename)
Dim bitBucket As System.IO.Stream = System.IO.Stream.Null
Dim e As ZipEntry
For Each e in zip1
If (Not e.IsDirectory) And e.UsesEncryption Then
e.ExtractWithPassword(bitBucket, password)
End If
Next
End Using
success = True
Catch ex As Ionic.Zip.BadPasswordException
End Try
Return success
End Function
I use SharpZipLib in .NET to do this, here is a link to their wiki with a helper function for unzipping password protected zip files. Below is a copy of the helper function for VB.NET.
Imports ICSharpCode.SharpZipLib.Core
Imports ICSharpCode.SharpZipLib.Zip
Public Sub ExtractZipFile(archiveFilenameIn As String, password As String, outFolder As String)
Dim zf As ZipFile = Nothing
Try
Dim fs As FileStream = File.OpenRead(archiveFilenameIn)
zf = New ZipFile(fs)
If Not [String].IsNullOrEmpty(password) Then ' AES encrypted entries are handled automatically
zf.Password = password
End If
For Each zipEntry As ZipEntry In zf
If Not zipEntry.IsFile Then ' Ignore directories
Continue For
End If
Dim entryFileName As [String] = zipEntry.Name
' to remove the folder from the entry:- entryFileName = Path.GetFileName(entryFileName);
' Optionally match entrynames against a selection list here to skip as desired.
' The unpacked length is available in the zipEntry.Size property.
Dim buffer As Byte() = New Byte(4095) {} ' 4K is optimum
Dim zipStream As Stream = zf.GetInputStream(zipEntry)
' Manipulate the output filename here as desired.
Dim fullZipToPath As [String] = Path.Combine(outFolder, entryFileName)
Dim directoryName As String = Path.GetDirectoryName(fullZipToPath)
If directoryName.Length > 0 Then
Directory.CreateDirectory(directoryName)
End If
' Unzip file in buffered chunks. This is just as fast as unpacking to a buffer the full size
' of the file, but does not waste memory.
' The "Using" will close the stream even if an exception occurs.
Using streamWriter As FileStream = File.Create(fullZipToPath)
StreamUtils.Copy(zipStream, streamWriter, buffer)
End Using
Next
Finally
If zf IsNot Nothing Then
zf.IsStreamOwner = True ' Makes close also shut the underlying stream
' Ensure we release resources
zf.Close()
End If
End Try
End Sub
To test, you could create a file compare that looks at the file before it's zipped and again after it has been unzipped (size, date, etc...). You could even compare the contents if you wanted to use a simple test file, like a file with the text "TEST" inside. Lots of choices, depends on how much and how far you want to test.
There's not much built into the framework for doing this. Here's a big sloppy mess you could try using the SharpZipLib library:
public static bool CheckIfCorrectZipPassword(string fileName, string tempDirectory, string password)
{
byte[] buffer= new byte[2048];
int n;
bool isValid = true;
using (var raw = File.Open(fileName, FileMode.Open, FileAccess.Read))
{
using (var input = new ZipInputStream(raw))
{
ZipEntry e;
while ((e = input.GetNextEntry()) != null)
{
input.Password = password;
if (e.IsDirectory) continue;
string outputPath = Path.Combine(tempDirectory, e.FileName);
try
{
using (var output = File.Open(outputPath, FileMode.Create, FileAccess.ReadWrite))
{
while ((n = input.Read(buffer, 0, buffer.Length)) > 0)
{
output.Write(buffer, 0, n);
}
}
}
catch (ZipException ze)
{
if (ze.Message == "Invalid Password")
{
isValid = false;
}
}
finally
{
if (File.Exists(outputPath))
{
// careful, this can throw exceptions
File.Delete(outputPath);
}
}
if (!isValid)
{
break;
}
}
}
}
return isValid;
}
Apologies for the C#; should be fairly straightforward to convert to VB.NET.
精彩评论