Skip to content

Commit 2505508

Browse files
committed
Let the modified date/time be settable when writing a zip file
1 parent d046722 commit 2505508

3 files changed

Lines changed: 37 additions & 7 deletions

File tree

.gitignore

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,3 +24,8 @@ _testmain.go
2424
*.exe
2525
*.test
2626
*.prof
27+
28+
# Go dependencies
29+
vendor/
30+
Gopkg.toml
31+
Gopkg.lock

crypto.go

Lines changed: 22 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -15,12 +15,15 @@ import (
1515
"errors"
1616
"hash"
1717
"io"
18+
"time"
1819

1920
"golang.org/x/crypto/pbkdf2"
2021
)
2122

23+
// EncryptionMethod is a type which defines encryption methods
2224
type EncryptionMethod int
2325

26+
// Encryption methods and constants
2427
const (
2528
StandardEncryption EncryptionMethod = 1
2629
AES128Encryption EncryptionMethod = 2
@@ -388,7 +391,7 @@ func encryptStream(key []byte, w io.Writer) (io.Writer, error) {
388391
// data. The authcode will be written out in fileWriter.close().
389392
func newEncryptionWriter(w io.Writer, password passwordFn, fw *fileWriter, aesstrength byte) (io.Writer, error) {
390393
keysize := aesKeyLen(aesstrength)
391-
salt := make([]byte, keysize / 2)
394+
salt := make([]byte, keysize/2)
392395
_, err := rand.Read(salt[:])
393396
if err != nil {
394397
return nil, errors.New("zip: unable to generate random salt")
@@ -437,7 +440,8 @@ func (h *FileHeader) writeWinZipExtra() {
437440
h.Extra = append(h.Extra, buf[:]...)
438441
}
439442

440-
func (h *FileHeader) setEncryptionMethod(enc EncryptionMethod) {
443+
// SetEncryptionMethod sets the encryption method.
444+
func (h *FileHeader) SetEncryptionMethod(enc EncryptionMethod) {
441445
h.encryption = enc
442446
switch enc {
443447
case AES128Encryption:
@@ -467,17 +471,29 @@ func (h *FileHeader) SetPassword(password string) {
467471
// as a byte slice
468472
type passwordFn func() []byte
469473

470-
// Encrypt adds a file to the zip file using the provided name.
474+
// EncryptTime adds a file to the zip file using the provided name.
471475
// It returns a Writer to which the file contents should be written. File
472476
// contents will be encrypted with AES-256 using the given password. The
473477
// file's contents must be written to the io.Writer before the next call
474-
// to Create, CreateHeader, or Close.
475-
func (w *Writer) Encrypt(name string, password string, enc EncryptionMethod) (io.Writer, error) {
478+
// to Create, CreateHeader, or Close. It uses the provided modTime as
479+
// the file's last modified date&time
480+
func (w *Writer) EncryptTime(name string, password string, enc EncryptionMethod, modTime time.Time) (io.Writer, error) {
476481
fh := &FileHeader{
477482
Name: name,
478483
Method: Deflate,
479484
}
485+
fh.SetModTime(modTime)
480486
fh.SetPassword(password)
481-
fh.setEncryptionMethod(enc)
487+
fh.SetEncryptionMethod(enc)
482488
return w.CreateHeader(fh)
483489
}
490+
491+
// Encrypt adds a file to the zip file using the provided name.
492+
// It returns a Writer to which the file contents should be written. File
493+
// contents will be encrypted with AES-256 using the given password. The
494+
// file's contents must be written to the io.Writer before the next call
495+
// to Create, CreateHeader, or Close. It uses the current time as
496+
// the file's last modified date&time
497+
func (w *Writer) Encrypt(name string, password string, enc EncryptionMethod) (io.Writer, error) {
498+
return w.EncryptTime(name, password, enc, time.Now())
499+
}

crypto_test.go

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import (
55
"io"
66
"path/filepath"
77
"testing"
8+
"time"
89
)
910

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

236237
zipr, _ := NewReader(bytes.NewReader(raw.Bytes()), int64(raw.Len()))
237238
zipr.File[0].SetPassword("golang")
239+
240+
modifiedTime := zipr.File[0].FileHeader.ModTime()
241+
duration := time.Since(modifiedTime)
242+
// Take care of the 2 seconds granularity
243+
if duration.Seconds() <= -2000 || 4 <= duration.Seconds() {
244+
t.Errorf("Modified time is expected to be very recent")
245+
}
246+
238247
r, _ := zipr.File[0].Open()
239248
res := new(bytes.Buffer)
240249
io.Copy(res, r)

0 commit comments

Comments
 (0)