Skip to content

Commit

Permalink
Let the modified date/time be settable when writing a zip file
Browse files Browse the repository at this point in the history
  • Loading branch information
fperot74 committed Oct 22, 2019
1 parent d046722 commit 41d2e26
Show file tree
Hide file tree
Showing 3 changed files with 34 additions and 5 deletions.
5 changes: 5 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -24,3 +24,8 @@ _testmain.go
*.exe
*.test
*.prof

# Go dependencies
vendor/
Gopkg.toml
Gopkg.lock
23 changes: 19 additions & 4 deletions crypto.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,15 @@ import (
"errors"
"hash"
"io"
"time"

"golang.org/x/crypto/pbkdf2"
)

// EncryptionMethod is a type which defines encryption methods
type EncryptionMethod int

// Encryption methods and constants
const (
StandardEncryption EncryptionMethod = 1
AES128Encryption EncryptionMethod = 2
Expand Down Expand Up @@ -388,7 +391,7 @@ func encryptStream(key []byte, w io.Writer) (io.Writer, error) {
// data. The authcode will be written out in fileWriter.close().
func newEncryptionWriter(w io.Writer, password passwordFn, fw *fileWriter, aesstrength byte) (io.Writer, error) {
keysize := aesKeyLen(aesstrength)
salt := make([]byte, keysize / 2)
salt := make([]byte, keysize/2)
_, err := rand.Read(salt[:])
if err != nil {
return nil, errors.New("zip: unable to generate random salt")
Expand Down Expand Up @@ -467,17 +470,29 @@ func (h *FileHeader) SetPassword(password string) {
// as a byte slice
type passwordFn func() []byte

// Encrypt adds a file to the zip file using the provided name.
// EncryptTime adds a file to the zip file using the provided name.
// It returns a Writer to which the file contents should be written. File
// contents will be encrypted with AES-256 using the given password. The
// file's contents must be written to the io.Writer before the next call
// to Create, CreateHeader, or Close.
func (w *Writer) Encrypt(name string, password string, enc EncryptionMethod) (io.Writer, error) {
// to Create, CreateHeader, or Close. It uses the provided modTime as
// the file's last modified date&time
func (w *Writer) EncryptTime(name string, password string, enc EncryptionMethod, modTime time.Time) (io.Writer, error) {
fh := &FileHeader{
Name: name,
Method: Deflate,
}
fh.SetModTime(modTime)
fh.SetPassword(password)
fh.setEncryptionMethod(enc)
return w.CreateHeader(fh)
}

// Encrypt adds a file to the zip file using the provided name.
// It returns a Writer to which the file contents should be written. File
// contents will be encrypted with AES-256 using the given password. The
// file's contents must be written to the io.Writer before the next call
// to Create, CreateHeader, or Close. It uses the current time as
// the file's last modified date&time
func (w *Writer) Encrypt(name string, password string, enc EncryptionMethod) (io.Writer, error) {
return w.EncryptTime(name, password, enc, time.Now())
}
11 changes: 10 additions & 1 deletion crypto_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import (
"io"
"path/filepath"
"testing"
"time"
)

// Test simple password reading.
Expand Down Expand Up @@ -56,7 +57,7 @@ func TestPasswordHelloWorldAes(t *testing.T) {
var b bytes.Buffer
for _, f := range r.File {
if !f.IsEncrypted() {
t.Errorf("Expected %s to be encrypted.", f.FileInfo().Name)
t.Errorf("Expected %s to be encrypted.", f.FileInfo().Name())
}
f.SetPassword("golang")
rc, err := f.Open()
Expand Down Expand Up @@ -235,6 +236,14 @@ func TestZipCrypto(t *testing.T) {

zipr, _ := NewReader(bytes.NewReader(raw.Bytes()), int64(raw.Len()))
zipr.File[0].SetPassword("golang")

modifiedTime := zipr.File[0].FileHeader.ModTime()
duration := time.Since(modifiedTime)
// Take care of the 2 seconds granularity
if duration.Seconds() <= -2000 || 4 <= duration.Seconds() {
t.Errorf("Modified time is expected to be very recent")
}

r, _ := zipr.File[0].Open()
res := new(bytes.Buffer)
io.Copy(res, r)
Expand Down

0 comments on commit 41d2e26

Please sign in to comment.