├── .eslintrc.js ├── .github └── workflows │ └── codesee-arch-diagram.yml ├── .gitignore ├── .npmignore ├── .npmrc ├── .travis.yml ├── CHANGELOG.md ├── LICENSE ├── README.md ├── index.js ├── lib ├── aes │ ├── aes-hmac-etm-stream.js │ └── zip-aes-stream.js ├── zip-encrypted.js └── zip20 │ ├── CryptoCipher.js │ ├── crc.js │ ├── crypto-stream.js │ ├── decrypto-stream.js │ └── zip-crypto-stream.js ├── package-lock.json ├── package.json ├── support ├── issue-16.js ├── issue-17.js └── issue-30.js └── test ├── aes-hmac-etm-stream.js ├── as-stream.js ├── crypto-stream.js ├── resources ├── dir │ └── sub │ │ └── test.txt ├── empty-file.txt └── test.txt ├── zip-aes.js ├── zip-encrypted.js └── zip20.js /.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | 'env': { 3 | 'node': true, 4 | 'es6': true, 5 | 'mocha': true 6 | }, 7 | 'extends': 'eslint:recommended', 8 | 'globals': { 9 | 'Atomics': 'readonly', 10 | 'SharedArrayBuffer': 'readonly' 11 | }, 12 | 'parserOptions': { 13 | 'ecmaVersion': 2015 14 | }, 15 | 'rules': { 16 | 'indent': [ 17 | 'error', 18 | 4 19 | ], 20 | 'quotes': [ 21 | 'error', 22 | 'single' 23 | ], 24 | 'semi': [ 25 | 'error', 26 | 'always' 27 | ] 28 | } 29 | }; -------------------------------------------------------------------------------- /.github/workflows/codesee-arch-diagram.yml: -------------------------------------------------------------------------------- 1 | on: 2 | push: 3 | branches: 4 | - master 5 | pull_request_target: 6 | types: [opened, synchronize, reopened] 7 | 8 | name: CodeSee Map 9 | 10 | jobs: 11 | test_map_action: 12 | runs-on: ubuntu-latest 13 | continue-on-error: true 14 | name: Run CodeSee Map Analysis 15 | steps: 16 | - name: checkout 17 | id: checkout 18 | uses: actions/checkout@v2 19 | with: 20 | repository: ${{ github.event.pull_request.head.repo.full_name }} 21 | ref: ${{ github.event.pull_request.head.ref }} 22 | fetch-depth: 0 23 | 24 | # codesee-detect-languages has an output with id languages. 25 | - name: Detect Languages 26 | id: detect-languages 27 | uses: Codesee-io/codesee-detect-languages-action@latest 28 | 29 | - name: Configure JDK 16 30 | uses: actions/setup-java@v2 31 | if: ${{ fromJSON(steps.detect-languages.outputs.languages).java }} 32 | with: 33 | java-version: '16' 34 | distribution: 'zulu' 35 | 36 | # CodeSee Maps Go support uses a static binary so there's no setup step required. 37 | 38 | - name: Configure Node.js 14 39 | uses: actions/setup-node@v2 40 | if: ${{ fromJSON(steps.detect-languages.outputs.languages).javascript }} 41 | with: 42 | node-version: '14' 43 | 44 | - name: Configure Python 3.x 45 | uses: actions/setup-python@v2 46 | if: ${{ fromJSON(steps.detect-languages.outputs.languages).python }} 47 | with: 48 | python-version: '3.x' 49 | architecture: 'x64' 50 | 51 | - name: Configure Ruby '3.x' 52 | uses: ruby/setup-ruby@v1 53 | if: ${{ fromJSON(steps.detect-languages.outputs.languages).ruby }} 54 | with: 55 | ruby-version: '3.0' 56 | 57 | # CodeSee Maps Rust support uses a static binary so there's no setup step required. 58 | 59 | - name: Generate Map 60 | id: generate-map 61 | uses: Codesee-io/codesee-map-action@latest 62 | with: 63 | step: map 64 | github_ref: ${{ github.ref }} 65 | languages: ${{ steps.detect-languages.outputs.languages }} 66 | 67 | - name: Upload Map 68 | id: upload-map 69 | uses: Codesee-io/codesee-map-action@latest 70 | with: 71 | step: mapUpload 72 | api_token: ${{ secrets.CODESEE_ARCH_DIAG_API_TOKEN }} 73 | github_ref: ${{ github.ref }} 74 | 75 | - name: Insights 76 | id: insights 77 | uses: Codesee-io/codesee-map-action@latest 78 | with: 79 | step: insights 80 | api_token: ${{ secrets.CODESEE_ARCH_DIAG_API_TOKEN }} 81 | github_ref: ${{ github.ref }} 82 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | yarn-debug.log* 6 | yarn-error.log* 7 | 8 | # Runtime data 9 | pids 10 | *.pid 11 | *.seed 12 | *.pid.lock 13 | 14 | # Directory for instrumented libs generated by jscoverage/JSCover 15 | lib-cov 16 | 17 | # Coverage directory used by tools like istanbul 18 | coverage 19 | 20 | # nyc test coverage 21 | .nyc_output 22 | 23 | # Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files) 24 | .grunt 25 | 26 | # Bower dependency directory (https://bower.io/) 27 | bower_components 28 | 29 | # node-waf configuration 30 | .lock-wscript 31 | 32 | # Compiled binary addons (https://nodejs.org/api/addons.html) 33 | build/Release 34 | 35 | # Dependency directories 36 | node_modules/ 37 | jspm_packages/ 38 | 39 | # TypeScript v1 declaration files 40 | typings/ 41 | 42 | # Optional npm cache directory 43 | .npm 44 | 45 | # Optional eslint cache 46 | .eslintcache 47 | 48 | # Optional REPL history 49 | .node_repl_history 50 | 51 | # Output of 'npm pack' 52 | *.tgz 53 | 54 | # Yarn Integrity file 55 | .yarn-integrity 56 | 57 | # dotenv environment variables file 58 | .env 59 | 60 | # next.js build output 61 | .next 62 | 63 | .idea/ 64 | *.iml 65 | /target/ 66 | -------------------------------------------------------------------------------- /.npmignore: -------------------------------------------------------------------------------- 1 | .idea 2 | *iml 3 | .travis.yml 4 | .eslintrc.js 5 | test 6 | target 7 | support 8 | coverage 9 | .nyc_output 10 | *zip -------------------------------------------------------------------------------- /.npmrc: -------------------------------------------------------------------------------- 1 | registry=https://registry.npmjs.org -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | os: linux 2 | dist: focal 3 | language: node_js 4 | node_js: 5 | - "16" 6 | - "18" 7 | - "20" 8 | before_install: 9 | - sudo apt-get install p7zip-full 10 | after_success: npm run coverage 11 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | ## 2.0.0 2 | 3 | Update all dependencies to latest. 4 | 5 | Require Node.js 16 or later. 6 | 7 | ## 1.0.10 8 | compress-commons updated to 4.1.1, zip-stream updated to 4.1.0 - see https://github.com/artem-karpenko/archiver-zip-encrypted/pull/28 9 | 10 | ## 1.0.9 11 | Updated dev dependencies, bumped patch version of zip-stream 12 | 13 | ## 1.0.8 14 | Removed `express` dependency accidentally introduced during tests 15 | 16 | ## 1.0.7 17 | Fixed encryption of directory entries. 18 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2019 Artem Karpenko. 2 | 3 | Permission is hereby granted, free of charge, to any person 4 | obtaining a copy of this software and associated documentation 5 | files (the "Software"), to deal in the Software without 6 | restriction, including without limitation the rights to use, 7 | copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | copies of the Software, and to permit persons to whom the 9 | Software is furnished to do so, subject to the following 10 | conditions: 11 | 12 | The above copyright notice and this permission notice shall be 13 | included in all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 16 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 17 | OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 18 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 19 | HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 20 | WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 21 | FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 22 | OTHER DEALINGS IN THE SOFTWARE. -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # archiver-zip-encrypted 2 | 3 | > AES-256 and legacy Zip 2.0 encryption for Zip files. 4 | 5 | [![Build Status](https://travis-ci.org/artem-karpenko/archiver-zip-encrypted.svg?branch=master)](https://travis-ci.org/artem-karpenko/archiver-zip-encrypted) 6 | [![Coverage Status](https://coveralls.io/repos/github/artem-karpenko/archiver-zip-encrypted/badge.svg)](https://coveralls.io/github/artem-karpenko/archiver-zip-encrypted) 7 | 8 | Plugin for [archiver](https://www.npmjs.com/package/archiver) that adds encryption 9 | capabilities to Zip compression. Pure JS, no external zip software needed. 10 | 11 | ## Install 12 | 13 | ```shell 14 | npm install archiver-zip-encrypted --save 15 | ``` 16 | 17 | ## Usage 18 | 19 | ```js 20 | const archiver = require('archiver'); 21 | 22 | // register format for archiver 23 | // note: only do it once per Node.js process/application, as duplicate registration will throw an error 24 | archiver.registerFormat('zip-encrypted', require("archiver-zip-encrypted")); 25 | 26 | // create archive and specify method of encryption and password 27 | let archive = archiver.create('zip-encrypted', {zlib: {level: 8}, encryptionMethod: 'aes256', password: '123'}); 28 | archive.append('File contents', {name: 'file.name'}) 29 | // ... add contents to archive as usual using archiver 30 | ``` 31 | ## Encryption methods 32 | 33 | Plugin supports 2 encryption methods: 34 | 35 | * 'aes256' - this is implementation of AES-256 encryption introduced by WinZip in 2003. 36 | It is the most safe option in regards of encryption, but limits possibilities of opening resulting archives. 37 | It's known to be supported by recent versions 7-Zip and WinZip. It is NOT supported by 38 | Linux unzip 6.00 (by Info-Zip). It is also NOT supported by Windows explorer (it's possible to browse contents of archive 39 | but not possible to view or extract files, i.e. perform operations that require decryption), even in Windows 10. 40 | * 'zip20' - this is implementation of legacy Zip 2.0 encryption (also called "ZipCrypto" in 7-Zip application). 41 | This is the first encryption method added to Zip format and hence is widely supported, in particular 42 | by standard tools in Linux and Windows. However its security is proven to be breakable 43 | so I would not recommend using it unless you absolutely have to make it work w/o external software. 44 | 45 | For more information on these encryption methods and its drawbacks in particular see [WinZip documentation](http://kb.winzip.com/help/RU/WZ/help_encryption.htm). 46 | It's worth noting that neither of these encryption methods encrypt file names and their metainformation, 47 | such as original size, filesystem dates, permissions etc. -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | module.exports = require('./lib/zip-encrypted'); -------------------------------------------------------------------------------- /lib/aes/aes-hmac-etm-stream.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const inherits = require('util').inherits; 4 | const {Transform} = require('stream'); 5 | const crypto = require('crypto'); 6 | const aes = require('aes-js'); 7 | 8 | const SALT_LENGTH = 16; 9 | const KEY_LENGTH = 32; 10 | const COMPOSITE_KEY_LENGTH = 2 * KEY_LENGTH + 2; 11 | const PBKDF2_ITERATION_COUNT = 1000; 12 | 13 | /** 14 | * Override increment to behave like in Zip implementation 15 | */ 16 | aes.Counter.prototype.increment = function() { 17 | for (var i = 0; i < 16; i++) { 18 | if (this._counter[i] === 255) { 19 | this._counter[i] = 0; 20 | } else { 21 | this._counter[i]++; 22 | break; 23 | } 24 | } 25 | }; 26 | 27 | /** 28 | * Transform stream that encodes data with AES stream and prepends additional data for authentication and verification: 29 | * ${salt}${passwordVerifier}${encodedData}${hmac} 30 | */ 31 | function AesHmacEtmStream(options = {key: null, salt: null, transformOptions: {}}) { 32 | if (!(this instanceof AesHmacEtmStream)) { 33 | return new AesHmacEtmStream(options); 34 | } 35 | Transform.call(this, options); 36 | 37 | this.salt = options.salt; 38 | if (!this.salt) { 39 | this.salt = crypto.randomBytes(SALT_LENGTH); 40 | } 41 | 42 | this.key = this.deriveKey(this.salt, options.key); 43 | // apparently WinZip's AES-CTR implementation uses nonce with 1st byte set to 1 and zeroes to others 44 | this.cipher = new aes.ModeOfOperation.ctr(new Uint8Array(this.key.aesKey), 45 | new aes.Counter(new Uint8Array(Buffer.from('01000000000000000000000000000000', 'hex')))); 46 | this.hmac = crypto.createHmac('sha1', this.key.hmacKey); 47 | this.passwordVerifier = this.key.passwordVerifier; 48 | 49 | this.headerSent = false; 50 | this.totalSize = 0; 51 | } 52 | inherits(AesHmacEtmStream, Transform); 53 | 54 | AesHmacEtmStream.prototype.deriveKey = function (salt, key) { 55 | const compositeKey = crypto.pbkdf2Sync(key, salt, PBKDF2_ITERATION_COUNT, COMPOSITE_KEY_LENGTH, 'sha1'); 56 | return { 57 | aesKey: compositeKey.slice(0, KEY_LENGTH), 58 | hmacKey: compositeKey.slice(KEY_LENGTH, 2 * KEY_LENGTH), 59 | passwordVerifier: compositeKey.slice(2 * KEY_LENGTH) 60 | }; 61 | }; 62 | 63 | AesHmacEtmStream.prototype.getTotalSize = function () { 64 | return this.totalSize; 65 | }; 66 | 67 | AesHmacEtmStream.prototype.ensureHeaderSent = function() { 68 | if (!this.headerSent) { 69 | this.push(this.salt); 70 | this.totalSize += this.salt.length; 71 | 72 | this.push(this.passwordVerifier); 73 | this.totalSize += this.passwordVerifier.length; 74 | 75 | this.headerSent = true; 76 | } 77 | }; 78 | 79 | AesHmacEtmStream.prototype._transform = function (data, encoding, cb) { 80 | this.ensureHeaderSent(); 81 | 82 | let encoded = this.cipher.encrypt(new Uint8Array(data)); 83 | 84 | if (encoded.length > 0) { 85 | this.hmac.update(encoded); 86 | this.push(Buffer.from(encoded)); // TODO check for return value? 87 | this.totalSize += encoded.length; 88 | } 89 | 90 | cb(); 91 | }; 92 | 93 | AesHmacEtmStream.prototype._flush = function (cb) { 94 | // _transform is not called for non-file entries, such as directories 95 | this.ensureHeaderSent(); 96 | 97 | let hmacData = this.hmac.digest().slice(0, 10); 98 | this.push(hmacData); 99 | 100 | this.totalSize += hmacData.length; 101 | 102 | cb(); 103 | }; 104 | 105 | module.exports = AesHmacEtmStream; -------------------------------------------------------------------------------- /lib/aes/zip-aes-stream.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const inherits = require('util').inherits; 4 | const AesHmacEtmStream = require('./aes-hmac-etm-stream'); 5 | const ZipStream = require('zip-stream'); 6 | const {DeflateCRC32Stream, CRC32Stream} = require('crc32-stream'); 7 | const crc32 = require('buffer-crc32'); 8 | const constants = require('compress-commons/lib/archivers/zip/constants'); 9 | const zipUtil = require('compress-commons/lib/archivers/zip/util'); 10 | 11 | const ZIP_AES_METHOD = 99; 12 | 13 | /** 14 | * Overrides ZipStream with AES-256 encryption 15 | */ 16 | const ZipAesStream = function (options = {zlib: {}}) { 17 | if (!(this instanceof ZipAesStream)) { 18 | return new ZipAesStream(options); 19 | } 20 | 21 | this.key = options.password; 22 | if (!Buffer.isBuffer(this.key)) { 23 | this.key = Buffer.from(this.key); 24 | } 25 | 26 | ZipStream.call(this, options); 27 | }; 28 | inherits(ZipAesStream, ZipStream); 29 | 30 | function _buildAesExtraField(ae) { 31 | let buffer = Buffer.alloc(11); 32 | buffer.writeUInt16LE(0x9901, 0); // AES header ID 33 | buffer.writeUInt16LE(0x7, 2); // data size, hardcoded 34 | buffer.writeUInt16LE(0x1, 4); // AE-1, i.e. CRC is present 35 | buffer.writeUInt16LE(0x4541, 6); // vendor id, hardcoded 36 | buffer.writeInt8(0x3, 8); // encryption strength: AES-256 37 | buffer.writeUInt16LE(ae.getMethod(), 9); // actual compression method 38 | 39 | return buffer; 40 | } 41 | 42 | ZipAesStream.prototype._writeLocalFileHeader = function (ae) { 43 | let gpb = ae.getGeneralPurposeBit(); 44 | 45 | // set AES-specific fields 46 | gpb.useEncryption(true); 47 | ae.setExtra(Buffer.concat([ae.getExtra(), _buildAesExtraField(ae)])); 48 | ae.setMethod(ZIP_AES_METHOD); 49 | ae.setVersionNeededToExtract(51); 50 | 51 | ZipStream.prototype._writeLocalFileHeader.call(this, ae); 52 | }; 53 | 54 | ZipAesStream.prototype._writeCentralFileHeader = function(ae) { 55 | var gpb = ae.getGeneralPurposeBit(); 56 | var method = ae.getMethod(); 57 | var offsets = ae._offsets; 58 | 59 | var size = ae.getSize(); 60 | var compressedSize = ae.getCompressedSize(); 61 | 62 | if (ae.isZip64() || offsets.file > constants.ZIP64_MAGIC) { 63 | size = constants.ZIP64_MAGIC; 64 | compressedSize = constants.ZIP64_MAGIC; 65 | 66 | ae.setVersionNeededToExtract(constants.MIN_VERSION_ZIP64); 67 | 68 | var extraBuf = Buffer.concat([ 69 | zipUtil.getShortBytes(constants.ZIP64_EXTRA_ID), 70 | zipUtil.getShortBytes(24), 71 | zipUtil.getEightBytes(ae.getSize()), 72 | zipUtil.getEightBytes(ae.getCompressedSize()), 73 | zipUtil.getEightBytes(offsets.file) 74 | ], 28); 75 | 76 | ae.setExtra(Buffer.concat([ae.getExtra(), extraBuf])); 77 | } 78 | 79 | // signature 80 | this.write(zipUtil.getLongBytes(constants.SIG_CFH)); 81 | 82 | // version made by 83 | this.write(zipUtil.getShortBytes((ae.getPlatform() << 8) | constants.VERSION_MADEBY)); 84 | 85 | // version to extract and general bit flag 86 | this.write(zipUtil.getShortBytes(ae.getVersionNeededToExtract())); 87 | this.write(gpb.encode()); 88 | 89 | // compression method 90 | this.write(zipUtil.getShortBytes(method)); 91 | 92 | // datetime 93 | this.write(zipUtil.getLongBytes(ae.getTimeDos())); 94 | 95 | // crc32 checksum 96 | this.write(zipUtil.getLongBytes(ae.getCrc())); 97 | 98 | // sizes 99 | this.write(zipUtil.getLongBytes(compressedSize)); 100 | this.write(zipUtil.getLongBytes(size)); 101 | 102 | var name = ae.getName(); 103 | var comment = ae.getComment(); 104 | var extra = ae.getCentralDirectoryExtra(); 105 | 106 | if (gpb.usesUTF8ForNames()) { 107 | name = Buffer.from(name); 108 | comment = Buffer.from(comment); 109 | } 110 | 111 | // name length 112 | this.write(zipUtil.getShortBytes(name.length)); 113 | 114 | // extra length 115 | this.write(zipUtil.getShortBytes(extra.length)); 116 | 117 | // comments length 118 | this.write(zipUtil.getShortBytes(comment.length)); 119 | 120 | // disk number start 121 | this.write(constants.SHORT_ZERO); 122 | 123 | // internal attributes 124 | this.write(zipUtil.getShortBytes(ae.getInternalAttributes())); 125 | 126 | // external attributes 127 | this.write(zipUtil.getLongBytes(ae.getExternalAttributes())); 128 | 129 | // relative offset of LFH 130 | if (offsets.file > constants.ZIP64_MAGIC) { 131 | this.write(zipUtil.getLongBytes(constants.ZIP64_MAGIC)); 132 | } else { 133 | this.write(zipUtil.getLongBytes(offsets.file)); 134 | } 135 | 136 | // name 137 | this.write(name); 138 | 139 | // extra 140 | this.write(extra); 141 | 142 | // comment 143 | this.write(comment); 144 | }; 145 | 146 | ZipAesStream.prototype._appendBuffer = function(ae, source, callback) { 147 | ae.setSize(source.length); 148 | ae.setCompressedSize(source.length + 28); 149 | ae.setCrc(crc32.unsigned(source)); 150 | 151 | this._writeLocalFileHeader(ae); 152 | 153 | this._smartStream(ae, callback).end(source); 154 | }; 155 | 156 | /** 157 | * Pass stream from compressor through encryption stream 158 | */ 159 | ZipAesStream.prototype._smartStream = function (ae, callback) { 160 | var deflate = ae.getExtra().readInt16LE(9) > 0; 161 | var compressionStream = deflate ? new DeflateCRC32Stream(this.options.zlib) : new CRC32Stream(); 162 | var encryptionStream = new AesHmacEtmStream({key: this.key, salt: this.options.salt}); 163 | var error = null; 164 | 165 | function onEnd() { 166 | var digest = compressionStream.digest().readUInt32BE(0); 167 | ae.setCrc(digest); 168 | ae.setSize(compressionStream.size()); 169 | ae.setCompressedSize(encryptionStream.getTotalSize()); 170 | this._afterAppend(ae); 171 | callback(error, ae); 172 | } 173 | 174 | encryptionStream.once('end', onEnd.bind(this)); 175 | compressionStream.once('error', function (err) { 176 | error = err; 177 | }); 178 | 179 | compressionStream.pipe(encryptionStream).pipe(this, {end: false}); 180 | 181 | return compressionStream; 182 | }; 183 | 184 | module.exports = ZipAesStream; -------------------------------------------------------------------------------- /lib/zip-encrypted.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | /** 4 | * ZIP with encryption 5 | */ 6 | const inherits = require('util').inherits; 7 | const ZipCryptoStream = require('./zip20/zip-crypto-stream'); 8 | const ZipAesStream = require('./aes/zip-aes-stream'); 9 | const Zip = require('archiver/lib/plugins/zip'); 10 | 11 | /** 12 | * Options copied from Zip plugin in archiver, with inclusion of password and method of encryption 13 | * @constructor 14 | * @param {ZipOptions} [options] 15 | * @param {String | Buffer} [options.password] password for encrypted data 16 | * @param {String} [options.encryptionMethod] "aes256" for AES-256 or "zip20" for legacy Zip 2.0 encryption 17 | * @param {String} [options.comment] Sets the zip archive comment. 18 | * @param {Boolean} [options.forceLocalTime=false] Forces the archive to contain local file times instead of UTC. 19 | * @param {Boolean} [options.forceZip64=false] Forces the archive to contain ZIP64 headers. 20 | * @param {Boolean} [options.store=false] Sets the compression method to STORE. 21 | * @param {Object} [options.zlib] Passed to [zlib]{@link https://nodejs.org/api/zlib.html#zlib_class_options} 22 | */ 23 | const ZipEncrypted = function (options = {}) { 24 | if (!options.password) { 25 | throw new Error('options.password is required'); 26 | } 27 | if (!Buffer.isBuffer(options.password)) { 28 | options.password = Buffer.from(options.password, 'utf-8'); 29 | } 30 | 31 | if (!(this instanceof ZipEncrypted)) { 32 | return new ZipEncrypted(options); 33 | } 34 | 35 | Zip.call(this, options); 36 | 37 | switch (options.encryptionMethod) { 38 | case 'aes256': this.engine = new ZipAesStream(options); break; 39 | case 'zip20': this.engine = new ZipCryptoStream(options); break; 40 | default: throw new Error(`Unsupported encryption method: '${options.encryptionMethod}'. Please use either 'aes256' or 'zip20'.`); 41 | } 42 | }; 43 | inherits(ZipEncrypted, Zip); 44 | 45 | module.exports = ZipEncrypted; 46 | -------------------------------------------------------------------------------- /lib/zip20/CryptoCipher.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | /** 4 | * Implementation of "ZipCrypto"/"Zip 2.0 encryption" cipher used in Zip. 5 | * This is old and insecure algorithm, AES-based encryption has been introduced into ZIP format since then. 6 | * Yet, this is the only encryption method supported by Windows systems to open ZIP files as folders. 7 | */ 8 | 9 | const crc32 = require('./crc'); 10 | 11 | const _uint8 = n => n & 0xFF; 12 | const _uint32 = n => n & 0xFFFFFFFF; 13 | 14 | function CryptoCipher(key) { 15 | this.key = key; 16 | if (!Buffer.isBuffer(key)) { 17 | this.key = Buffer.from(this.key); 18 | } 19 | 20 | this._init(); 21 | } 22 | 23 | CryptoCipher.prototype._init = function () { 24 | this.key0 = 0x12345678; 25 | this.key1 = 0x23456789; 26 | this.key2 = 0x34567890; 27 | 28 | for (let b of this.key) { 29 | this._updateKeys(b); 30 | } 31 | }; 32 | 33 | CryptoCipher.prototype._updateKeys = function (b) { 34 | this.key0 = crc32(this.key0, b); 35 | this.key1 = _uint32(this.key1 + (this.key0 & 0xFF)); 36 | this.key1 = _uint32(Math.imul(this.key1, 134775813) + 1); 37 | this.key2 = crc32(this.key2, this.key1 >>> 24); 38 | }; 39 | 40 | CryptoCipher.prototype._streamByte = function () { 41 | let tmp = this.key2 | 2; 42 | return _uint8(Math.imul(tmp, (tmp ^ 1)) >>> 8); 43 | }; 44 | 45 | CryptoCipher.prototype._encryptByte = function (b) { 46 | let encryptedByte = this._streamByte() ^ b; 47 | this._updateKeys(b); 48 | return encryptedByte; 49 | }; 50 | 51 | CryptoCipher.prototype._decryptByte = function (b) { 52 | let decryptedByte = this._streamByte() ^ b; 53 | this._updateKeys(decryptedByte); 54 | return decryptedByte; 55 | }; 56 | 57 | CryptoCipher.prototype.encrypt = function (data) { 58 | let encryptedData = Buffer.alloc(Buffer.byteLength(data)), offset = 0; 59 | for (let b of data) { 60 | encryptedData.writeUInt8(this._encryptByte(b), offset++); 61 | } 62 | return encryptedData; 63 | }; 64 | 65 | CryptoCipher.prototype.decrypt = function (data) { 66 | let decryptedData = Buffer.alloc(Buffer.byteLength(data)), offset = 0; 67 | for (let b of data) { 68 | decryptedData.writeUInt8(this._decryptByte(b), offset++); 69 | } 70 | return decryptedData; 71 | }; 72 | 73 | module.exports = CryptoCipher; -------------------------------------------------------------------------------- /lib/zip20/crc.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Build CRC table 3 | */ 4 | const CRC_TABLE = []; 5 | for (let i = 0; i < 256; i++) { 6 | let r = i; 7 | for (let j = 0; j < 8; j++) { 8 | if ((r & 1) === 1) { 9 | r = (r >>> 1) ^ 0xedb88320; 10 | } else { 11 | r >>>= 1; 12 | } 13 | } 14 | CRC_TABLE[i] = r; 15 | } 16 | 17 | module.exports = function crc32(oldCrc, charAt) { 18 | return oldCrc >>> 8 ^ CRC_TABLE[(oldCrc ^ charAt) & 0xff]; 19 | }; -------------------------------------------------------------------------------- /lib/zip20/crypto-stream.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const inherits = require('util').inherits; 4 | const {Transform} = require('stream'); 5 | const crypto = require('crypto'); 6 | const CryptoCipher = require('./CryptoCipher'); 7 | 8 | const HEADER_LENGTH = 12; 9 | 10 | /** 11 | * Transform stream that encodes data with CryptoCipher 12 | */ 13 | function CryptoStream(options = {key: null, crc: null, transformOptions: {}}) { 14 | if (!(this instanceof CryptoStream)) { 15 | return new CryptoStream(options); 16 | } 17 | Transform.call(this, options); 18 | 19 | this.key = options.key; 20 | this.crc = options.crc; 21 | this.cipher = new CryptoCipher(this.key); 22 | 23 | this.headerSent = false; 24 | } 25 | inherits(CryptoStream, Transform); 26 | 27 | CryptoStream.prototype._encrypt = function (data) { 28 | return this.cipher.encrypt(data); 29 | }; 30 | 31 | CryptoStream.prototype._transform = function (data, encoding, cb) { 32 | if (!this.headerSent) { 33 | let header = crypto.randomBytes(HEADER_LENGTH); 34 | header.writeUInt16LE(this.crc.readUInt16BE(0), HEADER_LENGTH - 2); 35 | 36 | let encryptedHeader = this._encrypt(header); 37 | 38 | this.push(encryptedHeader); 39 | 40 | this.headerSent = true; 41 | } 42 | 43 | let encrypted = this._encrypt(data); 44 | 45 | if (encrypted.length > 0) { 46 | this.push(encrypted); 47 | } 48 | 49 | cb(); 50 | }; 51 | 52 | module.exports = CryptoStream; -------------------------------------------------------------------------------- /lib/zip20/decrypto-stream.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const inherits = require('util').inherits; 4 | const {Transform} = require('stream'); 5 | const CryptoCipher = require('./CryptoCipher'); 6 | 7 | const HEADER_LENGTH = 12; 8 | 9 | /** 10 | * Transform stream that encodes data with CryptoCipher 11 | */ 12 | function DecryptoStream(options = {key: null, crc: null, transformOptions: {}}) { 13 | if (!(this instanceof DecryptoStream)) { 14 | return new DecryptoStream(options); 15 | } 16 | Transform.call(this, options); 17 | 18 | this.key = options.key; 19 | this.crc = options.crc; 20 | this.cipher = new CryptoCipher(this.key); 21 | 22 | this.header = Buffer.alloc(0); 23 | this.headerProcessed = false; 24 | this.totalSize = 0; 25 | } 26 | 27 | inherits(DecryptoStream, Transform); 28 | 29 | DecryptoStream.prototype.getTotalSize = function () { 30 | return this.totalSize; 31 | }; 32 | 33 | DecryptoStream.prototype._decrypt = function (data) { 34 | return this.cipher.decrypt(data); 35 | }; 36 | 37 | DecryptoStream.prototype._transform = function (data, encoding, cb) { 38 | if (!this.headerProcessed) { 39 | this.header = Buffer.concat([this.header, data]); 40 | if (this.header.length > HEADER_LENGTH) { 41 | data = data.slice(HEADER_LENGTH - this.header.length); 42 | this.header = this.header.slice(0, HEADER_LENGTH); 43 | 44 | this._decrypt(this.header); 45 | 46 | this.headerProcessed = true; 47 | } else { 48 | data = Buffer.alloc(0); 49 | } 50 | } 51 | 52 | let decrypted = this._decrypt(data); 53 | 54 | if (decrypted.length > 0) { 55 | this.push(decrypted); 56 | this.totalSize += decrypted.length; 57 | } 58 | 59 | cb(); 60 | }; 61 | 62 | module.exports = DecryptoStream; -------------------------------------------------------------------------------- /lib/zip20/zip-crypto-stream.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const inherits = require('util').inherits; 4 | const CryptoStream = require('./crypto-stream'); 5 | const ZipStream = require('zip-stream'); 6 | const {DeflateCRC32Stream, CRC32Stream} = require('crc32-stream'); 7 | // var crc32 = require('buffer-crc32'); 8 | const constants = require('compress-commons/lib/archivers/zip/constants'); 9 | 10 | /** 11 | * Overrides ZipStream with ZipCrypto/Zip2.0 encryption 12 | */ 13 | const ZipCryptoStream = function (options = {zlib: {}}) { 14 | if (!(this instanceof ZipCryptoStream)) { 15 | return new ZipCryptoStream(options); 16 | } 17 | 18 | this.key = options.password; 19 | if (!Buffer.isBuffer(this.key)) { 20 | this.key = Buffer.from(options.password); 21 | } 22 | 23 | ZipStream.call(this, options); 24 | }; 25 | inherits(ZipCryptoStream, ZipStream); 26 | 27 | ZipCryptoStream.prototype._writeLocalFileHeader = function (ae) { 28 | // set encryption 29 | ae.getGeneralPurposeBit().useEncryption(true); 30 | ZipStream.prototype._writeLocalFileHeader.call(this, ae); 31 | }; 32 | 33 | /** 34 | * As opposed to original implementation which streamed deflated data into target stream, 35 | * this implementation buffers deflated data. This is done for 2 reasons: 36 | * 1) encryption header is prepended to encrypted file datamust include bytes from file's CRC 37 | * 2) using data descriptor along with ZipCrypto encryption seems unsupported (this may be 38 | * the consequence of 1st reason but I don't know that for sure) 39 | * 40 | * The buffering currently done in memory. If a need arises, need to add disk buffering. 41 | */ 42 | ZipCryptoStream.prototype._smartStream = function (ae, callback) { 43 | let deflate = ae.getMethod() === constants.METHOD_DEFLATED; 44 | let compressionStream = deflate ? new DeflateCRC32Stream(this.options.zlib) : new CRC32Stream(); 45 | let error = null; 46 | let bufferedData = []; 47 | 48 | compressionStream.once('error', function (err) { 49 | error = err; 50 | }); 51 | 52 | compressionStream.on('data', (data) => { 53 | bufferedData.push(data); 54 | }); 55 | 56 | compressionStream.once('end', () => { 57 | let crc = compressionStream.digest(); 58 | 59 | // gather complete information for CRC and sizes 60 | ae.setCrc(crc.readUInt32BE(0)); 61 | ae.setSize(compressionStream.size()); 62 | ae.setCompressedSize(compressionStream.size(true) + 12); 63 | 64 | // write local header now 65 | this._writeLocalFileHeader(ae); 66 | 67 | // write all buffered data to encrypt stream 68 | let encrypt = new CryptoStream({key: this.key, crc}); 69 | let writes = []; 70 | for (let chunk of bufferedData) { 71 | writes.push(() => writeBufferToStream(encrypt, chunk)); 72 | } 73 | promiseSerial(writes).then(() => encrypt.end()); 74 | 75 | encrypt.once('end', () => { 76 | this._afterAppend(ae); 77 | callback(error, ae); 78 | }); 79 | encrypt.once('error', function (err) { 80 | error = err; 81 | }); 82 | 83 | encrypt.pipe(this, {end: false}); 84 | }); 85 | 86 | return compressionStream; 87 | }; 88 | 89 | ZipCryptoStream.prototype._appendBuffer = function(ae, source, callback) { 90 | ae.setSize(source.length); 91 | ae.setCompressedSize(source.length); 92 | ae.getGeneralPurposeBit().useDataDescriptor(false); 93 | 94 | // we will write local file header after we get CRC back 95 | // it seems as if using data descriptor is not supported when encrypting data with ZipCrypto 96 | // so we have to write CRC into local file header 97 | // this._writeLocalFileHeader(ae); 98 | 99 | this._smartStream(ae, callback).end(source); 100 | }; 101 | 102 | ZipCryptoStream.prototype._appendStream = function(ae, source, callback) { 103 | ae.setVersionNeededToExtract(constants.MIN_VERSION_DATA_DESCRIPTOR); 104 | 105 | ae.getGeneralPurposeBit().useDataDescriptor(false); 106 | // we will write local file header after we get CRC back 107 | // it seems as if using data descriptor is not supported when encrypting data with ZipCrypto 108 | // so we have to write CRC into local file header 109 | // this._writeLocalFileHeader(ae); 110 | 111 | var smart = this._smartStream(ae, callback); 112 | source.once('error', function(err) { 113 | smart.emit('error', err); 114 | smart.end(); 115 | }); 116 | source.pipe(smart); 117 | }; 118 | 119 | function writeBufferToStream(writable, data) { 120 | return new Promise((resolve, reject) => { 121 | writable.write(data, (err) => { 122 | if (err) { 123 | reject(); 124 | } else { 125 | resolve(); 126 | } 127 | }); 128 | }); 129 | } 130 | 131 | /** 132 | * Execute promises sequentially. Input is an array of functions that return promises to execute. 133 | */ 134 | const promiseSerial = funcs => 135 | funcs.reduce((promise, func) => 136 | promise.then(result => 137 | func().then(Array.prototype.concat.bind(result))), 138 | Promise.resolve([])); 139 | 140 | module.exports = ZipCryptoStream; -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "archiver-zip-encrypted", 3 | "version": "2.0.0", 4 | "description": "AES-256 and legacy Zip 2.0 encryption for Zip files", 5 | "dependencies": { 6 | "aes-js": "^3.1.2", 7 | "archiver": "^7.0.0", 8 | "archiver-utils": "^5.0.1", 9 | "buffer-crc32": "^1.0.0", 10 | "compress-commons": "^6.0.0", 11 | "crc32-stream": "^6.0.0", 12 | "zip-stream": "^6.0.0" 13 | }, 14 | "devDependencies": { 15 | "coveralls": "^3.1.1", 16 | "eslint": "^8.57.0", 17 | "mocha": "^10.3.0", 18 | "nyc": "^15.1.0", 19 | "rimraf": "^5.0.5", 20 | "should": "^13.2.3" 21 | }, 22 | "scripts": { 23 | "pretest": "eslint .", 24 | "test": "nyc --reporter=html mocha", 25 | "coverage": "nyc report --reporter=text-lcov " 26 | }, 27 | "repository": { 28 | "type": "git", 29 | "url": "git+https://github.com/artem-karpenko/archiver-zip-encrypted.git" 30 | }, 31 | "author": "Atrem Karpenko ", 32 | "license": "MIT", 33 | "bugs": { 34 | "url": "https://github.com/artem-karpenko/archiver-zip-encrypted/issues" 35 | }, 36 | "homepage": "https://github.com/artem-karpenko/archiver-zip-encrypted#readme", 37 | "keywords": [ 38 | "zip", 39 | "encryption", 40 | "aes", 41 | "archiver", 42 | "password" 43 | ], 44 | "engines": { 45 | "node": ">=16" 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /support/issue-16.js: -------------------------------------------------------------------------------- 1 | const archiver = require('archiver'); 2 | const fs = require('fs'); 3 | 4 | archiver.registerFormat('zip-encrypted', require('../')); 5 | let archive = archiver.create('zip-encrypted', { 6 | zlib: {level: 4}, encryptionMethod: 'aes256', password: '123' 7 | }); 8 | archive.append(fs.readFileSync('C:\\ffmpeg-20190428-45048ec-win64-static.zip'), {name: 'backupZip.zip'}); 9 | archive.finalize(); 10 | let out = fs.createWriteStream('aes123.zip'); 11 | archive.pipe(out); 12 | 13 | // out.on('close', () => { 14 | // console.log('close'); 15 | // }); -------------------------------------------------------------------------------- /support/issue-17.js: -------------------------------------------------------------------------------- 1 | const archiver = require('archiver'); 2 | const fs = require('fs'); 3 | 4 | const express = require('express'); 5 | const app = express(); 6 | const port = 3000; 7 | 8 | // register format for archiver 9 | archiver.registerFormat( 10 | 'zip-encrypted', 11 | require('../') 12 | ); 13 | 14 | app.get('/', (req, res) => { 15 | // create archive and specify method of encryption and password 16 | const archive = archiver.create('zip-encrypted', { 17 | zlib: { level: 9 }, 18 | encryptionMethod: 'zip20', 19 | password: Buffer.from('123') 20 | }); 21 | 22 | archive.on('error', err => { 23 | console.log(err); 24 | res.status(500).send({ error: err.message }); 25 | }); 26 | 27 | res.attachment('archive.zip'); 28 | 29 | archive.pipe(res); 30 | archive.append(fs.createReadStream('./resources/test.txt'), { name: 'data.txt' }); 31 | archive.finalize(); 32 | 33 | }); 34 | 35 | app.listen(port, () => console.log(`Example app listening on port ${port}!`)); -------------------------------------------------------------------------------- /support/issue-30.js: -------------------------------------------------------------------------------- 1 | const archiver = require('archiver'); 2 | const fs = require('fs'); 3 | 4 | const LARGE_FILE = 'C:\\Users\\gooyo\\Downloads\\Blade Runner 2049 (2017) BDRip 720p.mkv'; 5 | 6 | // register format for archiver 7 | archiver.registerFormat( 8 | 'zip-encrypted', 9 | require('../') 10 | ); 11 | 12 | // create archive and specify method of encryption and password 13 | const archive = archiver.create('zip-encrypted', { 14 | zlib: { level: 4, chunkSize: 10 * 1024 * 1024 }, 15 | encryptionMethod: 'aes256', 16 | password: Buffer.from('123') 17 | }); 18 | 19 | archive.on('error', err => { 20 | console.log(err); 21 | }); 22 | 23 | archive.append(fs.createReadStream(LARGE_FILE), { name: 'data.mkv' }); 24 | // archive.append(fs.createReadStream(LARGE_FILE), { name: 'data.mkv' }); 25 | // archive.append(fs.createReadStream('./issue-30.js'), { name: 'data.txt' }); 26 | archive.finalize(); 27 | 28 | let out = fs.createWriteStream('aes-large-orig.zip'); 29 | archive.pipe(out); -------------------------------------------------------------------------------- /test/aes-hmac-etm-stream.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const AesHmacEtmStream = require('../lib/aes/aes-hmac-etm-stream'); 4 | const crypto = require('crypto'); 5 | const aes = require('aes-js'); 6 | require('should'); 7 | 8 | describe('aes-hmac-etm-stream', () => { 9 | it('should encode data which is later decoded by aes-js', (done) => { 10 | let salt = Buffer.from('1234567890123456', 'ascii'); 11 | let key = Buffer.from('12345678901234567890123456789012', 'ascii'); 12 | let stream = AesHmacEtmStream({ 13 | salt: salt, 14 | key: key}); 15 | 16 | let data = crypto.randomBytes(3000); 17 | stream.write(data); 18 | 19 | let anotherData = crypto.randomBytes(3000); 20 | stream.write(anotherData); 21 | 22 | data = Buffer.concat([data, anotherData]); 23 | 24 | stream.end(); 25 | 26 | let encodedData = Buffer.alloc(0); 27 | stream.on('data', data => { 28 | encodedData = Buffer.concat([encodedData, data]); 29 | }); 30 | 31 | stream.on('end', () => { 32 | const hmacLength = 10; 33 | 34 | encodedData.should.have.length(16 + 2 + data.length + hmacLength); 35 | encodedData.slice(0, 16).should.eql(salt); 36 | 37 | let compositeKey = stream.deriveKey(salt, key); 38 | 39 | compositeKey.passwordVerifier.should.be.eql(encodedData.slice(16, 18)); 40 | 41 | let decipher = new aes.ModeOfOperation.ctr(new Uint8Array(compositeKey.aesKey), 42 | new aes.Counter(new Uint8Array(Buffer.from('01000000000000000000000000000000', 'hex')))); 43 | 44 | let decoded = Buffer.from(decipher.decrypt(new Uint8Array(encodedData.slice(18, encodedData.length - hmacLength)))); 45 | 46 | decoded.should.be.eql(data); 47 | 48 | done(); 49 | }); 50 | }); 51 | }); 52 | -------------------------------------------------------------------------------- /test/as-stream.js: -------------------------------------------------------------------------------- 1 | const fs = require('fs'); 2 | const rmrf = require('rimraf'); 3 | const ZipCryptoStream = require('../lib/zip20/zip-crypto-stream'); 4 | 5 | describe('using as stream', () => { 6 | beforeEach(() => { 7 | rmrf.sync('./target'); 8 | fs.mkdirSync('./target', {recursive: true}); 9 | }); 10 | 11 | it('should encrypt data and 7z and 7z will decrypt it', (done) => { 12 | fs.createReadStream('./test/resources/test.txt') 13 | .pipe(new ZipCryptoStream({password: '123', encryptionMethod: 'zip20'})) 14 | .pipe(fs.createWriteStream('./target/test.zip')) 15 | .on('finish', done); 16 | }); 17 | }); -------------------------------------------------------------------------------- /test/crypto-stream.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const fs = require('fs'); 4 | const CryptoStream = require('../lib/zip20/crypto-stream'); 5 | const DecryptoStream = require('../lib/zip20/decrypto-stream'); 6 | require('should'); 7 | 8 | describe('crypt-stream', () => { 9 | it('should encrypt and then decrypt stream', (done) => { 10 | let cryptoStream = CryptoStream({crc: Buffer.from('ABF033D8', 'hex'), key: '123'}); 11 | let decryptoStream = new DecryptoStream({crc: Buffer.from('ABF033D8', 'hex'), key: '123'}); 12 | 13 | let originalData = Buffer.alloc(0); 14 | let finalData = Buffer.alloc(0); 15 | fs.createReadStream('./test/resources/test.txt', {highWaterMark: 1024}) 16 | .on('data', (data) => { 17 | originalData = Buffer.concat([originalData, data]); 18 | }) 19 | .pipe(cryptoStream) 20 | .pipe(decryptoStream) 21 | .on('data', (data) => { 22 | finalData = Buffer.concat([finalData, data]); 23 | }) 24 | .on('end', () => { 25 | finalData.should.eql(originalData); 26 | done(); 27 | }); 28 | }); 29 | }); -------------------------------------------------------------------------------- /test/resources/dir/sub/test.txt: -------------------------------------------------------------------------------- 1 | 123 -------------------------------------------------------------------------------- /test/resources/empty-file.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/artem-karpenko/archiver-zip-encrypted/0be6b0e6cbc2c4fbd15342a4b1389862679d7668/test/resources/empty-file.txt -------------------------------------------------------------------------------- /test/resources/test.txt: -------------------------------------------------------------------------------- 1 | THE SONNETS 2 | 1 3 | 4 | From fairest creatures we desire increase, 5 | That thereby beauty’s rose might never die, 6 | But as the riper should by time decease, 7 | His tender heir might bear his memory: 8 | But thou contracted to thine own bright eyes, 9 | Feed’st thy light’s flame with self-substantial fuel, 10 | Making a famine where abundance lies, 11 | Thy self thy foe, to thy sweet self too cruel: 12 | Thou that art now the world’s fresh ornament, 13 | And only herald to the gaudy spring, 14 | Within thine own bud buriest thy content, 15 | And, tender churl, mak’st waste in niggarding: 16 | Pity the world, or else this glutton be, 17 | To eat the world’s due, by the grave and thee. 18 | 19 | 2 20 | 21 | When forty winters shall besiege thy brow, 22 | And dig deep trenches in thy beauty’s field, 23 | Thy youth’s proud livery so gazed on now, 24 | Will be a tattered weed of small worth held: 25 | Then being asked, where all thy beauty lies, 26 | Where all the treasure of thy lusty days; 27 | To say, within thine own deep sunken eyes, 28 | Were an all-eating shame, and thriftless praise. 29 | How much more praise deserv’d thy beauty’s use, 30 | If thou couldst answer ‘This fair child of mine 31 | Shall sum my count, and make my old excuse,’ 32 | Proving his beauty by succession thine. 33 | This were to be new made when thou art old, 34 | And see thy blood warm when thou feel’st it cold. 35 | 36 | 3 37 | 38 | Look in thy glass and tell the face thou viewest, 39 | Now is the time that face should form another, 40 | Whose fresh repair if now thou not renewest, 41 | Thou dost beguile the world, unbless some mother. 42 | For where is she so fair whose uneared womb 43 | Disdains the tillage of thy husbandry? 44 | Or who is he so fond will be the tomb 45 | Of his self-love to stop posterity? 46 | Thou art thy mother’s glass and she in thee 47 | Calls back the lovely April of her prime, 48 | So thou through windows of thine age shalt see, 49 | Despite of wrinkles this thy golden time. 50 | But if thou live remembered not to be, 51 | Die single and thine image dies with thee. 52 | 53 | 4 54 | 55 | Unthrifty loveliness why dost thou spend, 56 | Upon thy self thy beauty’s legacy? 57 | Nature’s bequest gives nothing but doth lend, 58 | And being frank she lends to those are free: 59 | Then beauteous niggard why dost thou abuse, 60 | The bounteous largess given thee to give? 61 | Profitless usurer why dost thou use 62 | So great a sum of sums yet canst not live? 63 | For having traffic with thy self alone, 64 | Thou of thy self thy sweet self dost deceive, 65 | Then how when nature calls thee to be gone, 66 | What acceptable audit canst thou leave? 67 | Thy unused beauty must be tombed with thee, 68 | Which used lives th’ executor to be. 69 | 70 | 5 71 | 72 | Those hours that with gentle work did frame 73 | The lovely gaze where every eye doth dwell 74 | Will play the tyrants to the very same, 75 | And that unfair which fairly doth excel: 76 | For never-resting time leads summer on 77 | To hideous winter and confounds him there, 78 | Sap checked with frost and lusty leaves quite gone, 79 | Beauty o’er-snowed and bareness every where: 80 | Then were not summer’s distillation left 81 | A liquid prisoner pent in walls of glass, 82 | Beauty’s effect with beauty were bereft, 83 | Nor it nor no remembrance what it was. 84 | But flowers distilled though they with winter meet, 85 | Leese but their show, their substance still lives sweet. 86 | 87 | 6 88 | 89 | Then let not winter’s ragged hand deface, 90 | In thee thy summer ere thou be distilled: 91 | Make sweet some vial; treasure thou some place, 92 | With beauty’s treasure ere it be self-killed: 93 | That use is not forbidden usury, 94 | Which happies those that pay the willing loan; 95 | That’s for thy self to breed another thee, 96 | Or ten times happier be it ten for one, 97 | Ten times thy self were happier than thou art, 98 | If ten of thine ten times refigured thee: 99 | Then what could death do if thou shouldst depart, 100 | Leaving thee living in posterity? 101 | Be not self-willed for thou art much too fair, 102 | To be death’s conquest and make worms thine heir. 103 | 104 | 7 105 | 106 | Lo in the orient when the gracious light 107 | Lifts up his burning head, each under eye 108 | Doth homage to his new-appearing sight, 109 | Serving with looks his sacred majesty, 110 | And having climbed the steep-up heavenly hill, 111 | Resembling strong youth in his middle age, 112 | Yet mortal looks adore his beauty still, 113 | Attending on his golden pilgrimage: 114 | But when from highmost pitch with weary car, 115 | Like feeble age he reeleth from the day, 116 | The eyes (fore duteous) now converted are 117 | From his low tract and look another way: 118 | So thou, thy self out-going in thy noon: 119 | Unlooked on diest unless thou get a son. 120 | 121 | 8 122 | 123 | Music to hear, why hear’st thou music sadly? 124 | Sweets with sweets war not, joy delights in joy: 125 | Why lov’st thou that which thou receiv’st not gladly, 126 | Or else receiv’st with pleasure thine annoy? 127 | If the true concord of well-tuned sounds, 128 | By unions married do offend thine ear, 129 | They do but sweetly chide thee, who confounds 130 | In singleness the parts that thou shouldst bear: 131 | Mark how one string sweet husband to another, 132 | Strikes each in each by mutual ordering; 133 | Resembling sire, and child, and happy mother, 134 | Who all in one, one pleasing note do sing: 135 | Whose speechless song being many, seeming one, 136 | Sings this to thee, ‘Thou single wilt prove none’. 137 | 138 | 9 139 | 140 | Is it for fear to wet a widow’s eye, 141 | That thou consum’st thy self in single life? 142 | Ah, if thou issueless shalt hap to die, 143 | The world will wail thee like a makeless wife, 144 | The world will be thy widow and still weep, 145 | That thou no form of thee hast left behind, 146 | When every private widow well may keep, 147 | By children’s eyes, her husband’s shape in mind: 148 | Look what an unthrift in the world doth spend 149 | Shifts but his place, for still the world enjoys it; 150 | But beauty’s waste hath in the world an end, 151 | And kept unused the user so destroys it: 152 | No love toward others in that bosom sits 153 | That on himself such murd’rous shame commits. 154 | 155 | 10 156 | 157 | For shame deny that thou bear’st love to any 158 | Who for thy self art so unprovident. 159 | Grant if thou wilt, thou art beloved of many, 160 | But that thou none lov’st is most evident: 161 | For thou art so possessed with murd’rous hate, 162 | That ’gainst thy self thou stick’st not to conspire, 163 | Seeking that beauteous roof to ruinate 164 | Which to repair should be thy chief desire: 165 | O change thy thought, that I may change my mind, 166 | Shall hate be fairer lodged than gentle love? 167 | Be as thy presence is gracious and kind, 168 | Or to thy self at least kind-hearted prove, 169 | Make thee another self for love of me, 170 | That beauty still may live in thine or thee. 171 | 172 | 11 173 | 174 | As fast as thou shalt wane so fast thou grow’st, 175 | In one of thine, from that which thou departest, 176 | And that fresh blood which youngly thou bestow’st, 177 | Thou mayst call thine, when thou from youth convertest, 178 | Herein lives wisdom, beauty, and increase, 179 | Without this folly, age, and cold decay, 180 | If all were minded so, the times should cease, 181 | And threescore year would make the world away: 182 | Let those whom nature hath not made for store, 183 | Harsh, featureless, and rude, barrenly perish: 184 | Look whom she best endowed, she gave thee more; 185 | Which bounteous gift thou shouldst in bounty cherish: 186 | She carved thee for her seal, and meant thereby, 187 | Thou shouldst print more, not let that copy die. 188 | 189 | 12 190 | 191 | When I do count the clock that tells the time, 192 | And see the brave day sunk in hideous night, 193 | When I behold the violet past prime, 194 | And sable curls all silvered o’er with white: 195 | When lofty trees I see barren of leaves, 196 | Which erst from heat did canopy the herd 197 | And summer’s green all girded up in sheaves 198 | Borne on the bier with white and bristly beard: 199 | Then of thy beauty do I question make 200 | That thou among the wastes of time must go, 201 | Since sweets and beauties do themselves forsake, 202 | And die as fast as they see others grow, 203 | And nothing ’gainst Time’s scythe can make defence 204 | Save breed to brave him, when he takes thee hence. 205 | 206 | 13 207 | 208 | O that you were your self, but love you are 209 | No longer yours, than you your self here live, 210 | Against this coming end you should prepare, 211 | And your sweet semblance to some other give. 212 | So should that beauty which you hold in lease 213 | Find no determination, then you were 214 | Your self again after your self’s decease, 215 | When your sweet issue your sweet form should bear. 216 | Who lets so fair a house fall to decay, 217 | Which husbandry in honour might uphold, 218 | Against the stormy gusts of winter’s day 219 | And barren rage of death’s eternal cold? 220 | O none but unthrifts, dear my love you know, 221 | You had a father, let your son say so. 222 | 223 | 14 224 | 225 | Not from the stars do I my judgement pluck, 226 | And yet methinks I have astronomy, 227 | But not to tell of good, or evil luck, 228 | Of plagues, of dearths, or seasons’ quality, 229 | Nor can I fortune to brief minutes tell; 230 | Pointing to each his thunder, rain and wind, 231 | Or say with princes if it shall go well 232 | By oft predict that I in heaven find. 233 | But from thine eyes my knowledge I derive, 234 | And constant stars in them I read such art 235 | As truth and beauty shall together thrive 236 | If from thy self, to store thou wouldst convert: 237 | Or else of thee this I prognosticate, 238 | Thy end is truth’s and beauty’s doom and date. 239 | 240 | 15 241 | 242 | When I consider every thing that grows 243 | Holds in perfection but a little moment. 244 | That this huge stage presenteth nought but shows 245 | Whereon the stars in secret influence comment. 246 | When I perceive that men as plants increase, 247 | Cheered and checked even by the self-same sky: 248 | Vaunt in their youthful sap, at height decrease, 249 | And wear their brave state out of memory. 250 | Then the conceit of this inconstant stay, 251 | Sets you most rich in youth before my sight, 252 | Where wasteful time debateth with decay 253 | To change your day of youth to sullied night, 254 | And all in war with Time for love of you, 255 | As he takes from you, I engraft you new. 256 | 257 | 16 258 | 259 | But wherefore do not you a mightier way 260 | Make war upon this bloody tyrant Time? 261 | And fortify your self in your decay 262 | With means more blessed than my barren rhyme? 263 | Now stand you on the top of happy hours, 264 | And many maiden gardens yet unset, 265 | With virtuous wish would bear you living flowers, 266 | Much liker than your painted counterfeit: 267 | So should the lines of life that life repair 268 | Which this (Time’s pencil) or my pupil pen 269 | Neither in inward worth nor outward fair 270 | Can make you live your self in eyes of men. 271 | To give away your self, keeps your self still, 272 | And you must live drawn by your own sweet skill. 273 | 274 | 17 275 | 276 | Who will believe my verse in time to come 277 | If it were filled with your most high deserts? 278 | Though yet heaven knows it is but as a tomb 279 | Which hides your life, and shows not half your parts: 280 | If I could write the beauty of your eyes, 281 | And in fresh numbers number all your graces, 282 | The age to come would say this poet lies, 283 | Such heavenly touches ne’er touched earthly faces. 284 | So should my papers (yellowed with their age) 285 | Be scorned, like old men of less truth than tongue, 286 | And your true rights be termed a poet’s rage, 287 | And stretched metre of an antique song. 288 | But were some child of yours alive that time, 289 | You should live twice in it, and in my rhyme. 290 | 291 | 18 292 | 293 | Shall I compare thee to a summer’s day? 294 | Thou art more lovely and more temperate: 295 | Rough winds do shake the darling buds of May, 296 | And summer’s lease hath all too short a date: 297 | Sometime too hot the eye of heaven shines, 298 | And often is his gold complexion dimmed, 299 | And every fair from fair sometime declines, 300 | By chance, or nature’s changing course untrimmed: 301 | But thy eternal summer shall not fade, 302 | Nor lose possession of that fair thou ow’st, 303 | Nor shall death brag thou wand’rest in his shade, 304 | When in eternal lines to time thou grow’st, 305 | So long as men can breathe or eyes can see, 306 | So long lives this, and this gives life to thee. 307 | 308 | 19 309 | 310 | Devouring Time blunt thou the lion’s paws, 311 | And make the earth devour her own sweet brood, 312 | Pluck the keen teeth from the fierce tiger’s jaws, 313 | And burn the long-lived phoenix, in her blood, 314 | Make glad and sorry seasons as thou fleet’st, 315 | And do whate’er thou wilt swift-footed Time 316 | To the wide world and all her fading sweets: 317 | But I forbid thee one most heinous crime, 318 | O carve not with thy hours my love’s fair brow, 319 | Nor draw no lines there with thine antique pen, 320 | Him in thy course untainted do allow, 321 | For beauty’s pattern to succeeding men. 322 | Yet do thy worst old Time: despite thy wrong, 323 | My love shall in my verse ever live young. 324 | 325 | 20 326 | 327 | A woman’s face with nature’s own hand painted, 328 | Hast thou the master mistress of my passion, 329 | A woman’s gentle heart but not acquainted 330 | With shifting change as is false women’s fashion, 331 | An eye more bright than theirs, less false in rolling: 332 | Gilding the object whereupon it gazeth, 333 | A man in hue all hues in his controlling, 334 | Which steals men’s eyes and women’s souls amazeth. 335 | And for a woman wert thou first created, 336 | Till nature as she wrought thee fell a-doting, 337 | And by addition me of thee defeated, 338 | By adding one thing to my purpose nothing. 339 | But since she pricked thee out for women’s pleasure, 340 | Mine be thy love and thy love’s use their treasure. 341 | 342 | 21 343 | 344 | So is it not with me as with that muse, 345 | Stirred by a painted beauty to his verse, 346 | Who heaven it self for ornament doth use, 347 | And every fair with his fair doth rehearse, 348 | Making a couplement of proud compare 349 | With sun and moon, with earth and sea’s rich gems: 350 | With April’s first-born flowers and all things rare, 351 | That heaven’s air in this huge rondure hems. 352 | O let me true in love but truly write, 353 | And then believe me, my love is as fair, 354 | As any mother’s child, though not so bright 355 | As those gold candles fixed in heaven’s air: 356 | Let them say more that like of hearsay well, 357 | I will not praise that purpose not to sell. 358 | 359 | 22 360 | 361 | My glass shall not persuade me I am old, 362 | So long as youth and thou are of one date, 363 | But when in thee time’s furrows I behold, 364 | Then look I death my days should expiate. 365 | For all that beauty that doth cover thee, 366 | Is but the seemly raiment of my heart, 367 | Which in thy breast doth live, as thine in me, 368 | How can I then be elder than thou art? 369 | O therefore love be of thyself so wary, 370 | As I not for my self, but for thee will, 371 | Bearing thy heart which I will keep so chary 372 | As tender nurse her babe from faring ill. 373 | Presume not on thy heart when mine is slain, 374 | Thou gav’st me thine not to give back again. 375 | 376 | 23 377 | 378 | As an unperfect actor on the stage, 379 | Who with his fear is put beside his part, 380 | Or some fierce thing replete with too much rage, 381 | Whose strength’s abundance weakens his own heart; 382 | So I for fear of trust, forget to say, 383 | The perfect ceremony of love’s rite, 384 | And in mine own love’s strength seem to decay, 385 | O’ercharged with burthen of mine own love’s might: 386 | O let my looks be then the eloquence, 387 | And dumb presagers of my speaking breast, 388 | Who plead for love, and look for recompense, 389 | More than that tongue that more hath more expressed. 390 | O learn to read what silent love hath writ, 391 | To hear with eyes belongs to love’s fine wit. 392 | 393 | 24 394 | 395 | Mine eye hath played the painter and hath stelled, 396 | Thy beauty’s form in table of my heart, 397 | My body is the frame wherein ’tis held, 398 | And perspective it is best painter’s art. 399 | For through the painter must you see his skill, 400 | To find where your true image pictured lies, 401 | Which in my bosom’s shop is hanging still, 402 | That hath his windows glazed with thine eyes: 403 | Now see what good turns eyes for eyes have done, 404 | Mine eyes have drawn thy shape, and thine for me 405 | Are windows to my breast, where-through the sun 406 | Delights to peep, to gaze therein on thee; 407 | Yet eyes this cunning want to grace their art, 408 | They draw but what they see, know not the heart. 409 | 410 | 25 411 | 412 | Let those who are in favour with their stars, 413 | Of public honour and proud titles boast, 414 | Whilst I whom fortune of such triumph bars 415 | Unlooked for joy in that I honour most; 416 | Great princes’ favourites their fair leaves spread, 417 | But as the marigold at the sun’s eye, 418 | And in themselves their pride lies buried, 419 | For at a frown they in their glory die. 420 | The painful warrior famoused for fight, 421 | After a thousand victories once foiled, 422 | Is from the book of honour razed quite, 423 | And all the rest forgot for which he toiled: 424 | Then happy I that love and am beloved 425 | Where I may not remove nor be removed. 426 | 427 | 26 428 | 429 | Lord of my love, to whom in vassalage 430 | Thy merit hath my duty strongly knit; 431 | To thee I send this written embassage 432 | To witness duty, not to show my wit. 433 | Duty so great, which wit so poor as mine 434 | May make seem bare, in wanting words to show it; 435 | But that I hope some good conceit of thine 436 | In thy soul’s thought (all naked) will bestow it: 437 | Till whatsoever star that guides my moving, 438 | Points on me graciously with fair aspect, 439 | And puts apparel on my tattered loving, 440 | To show me worthy of thy sweet respect, 441 | Then may I dare to boast how I do love thee, 442 | Till then, not show my head where thou mayst prove me. 443 | 444 | 27 445 | 446 | Weary with toil, I haste me to my bed, 447 | The dear respose for limbs with travel tired, 448 | But then begins a journey in my head 449 | To work my mind, when body’s work’s expired. 450 | For then my thoughts (from far where I abide) 451 | Intend a zealous pilgrimage to thee, 452 | And keep my drooping eyelids open wide, 453 | Looking on darkness which the blind do see. 454 | Save that my soul’s imaginary sight 455 | Presents thy shadow to my sightless view, 456 | Which like a jewel (hung in ghastly night) 457 | Makes black night beauteous, and her old face new. 458 | Lo thus by day my limbs, by night my mind, 459 | For thee, and for my self, no quiet find. 460 | 461 | 28 462 | 463 | How can I then return in happy plight 464 | That am debarred the benefit of rest? 465 | When day’s oppression is not eased by night, 466 | But day by night and night by day oppressed. 467 | And each (though enemies to either’s reign) 468 | Do in consent shake hands to torture me, 469 | The one by toil, the other to complain 470 | How far I toil, still farther off from thee. 471 | I tell the day to please him thou art bright, 472 | And dost him grace when clouds do blot the heaven: 473 | So flatter I the swart-complexioned night, 474 | When sparkling stars twire not thou gild’st the even. 475 | But day doth daily draw my sorrows longer, 476 | And night doth nightly make grief’s length seem stronger 477 | 478 | 29 479 | 480 | When in disgrace with Fortune and men’s eyes, 481 | I all alone beweep my outcast state, 482 | And trouble deaf heaven with my bootless cries, 483 | And look upon my self and curse my fate, 484 | Wishing me like to one more rich in hope, 485 | Featured like him, like him with friends possessed, 486 | Desiring this man’s art, and that man’s scope, 487 | With what I most enjoy contented least, 488 | Yet in these thoughts my self almost despising, 489 | Haply I think on thee, and then my state, 490 | (Like to the lark at break of day arising 491 | From sullen earth) sings hymns at heaven’s gate, 492 | For thy sweet love remembered such wealth brings, 493 | That then I scorn to change my state with kings. 494 | 495 | 30 496 | 497 | When to the sessions of sweet silent thought, 498 | I summon up remembrance of things past, 499 | I sigh the lack of many a thing I sought, 500 | And with old woes new wail my dear time’s waste: 501 | Then can I drown an eye (unused to flow) 502 | For precious friends hid in death’s dateless night, 503 | And weep afresh love’s long since cancelled woe, 504 | And moan th’ expense of many a vanished sight. 505 | Then can I grieve at grievances foregone, 506 | And heavily from woe to woe tell o’er 507 | The sad account of fore-bemoaned moan, 508 | Which I new pay as if not paid before. 509 | But if the while I think on thee (dear friend) 510 | All losses are restored, and sorrows end. 511 | 512 | 31 513 | 514 | Thy bosom is endeared with all hearts, 515 | Which I by lacking have supposed dead, 516 | And there reigns love and all love’s loving parts, 517 | And all those friends which I thought buried. 518 | How many a holy and obsequious tear 519 | Hath dear religious love stol’n from mine eye, 520 | As interest of the dead, which now appear, 521 | But things removed that hidden in thee lie. 522 | Thou art the grave where buried love doth live, 523 | Hung with the trophies of my lovers gone, 524 | Who all their parts of me to thee did give, 525 | That due of many, now is thine alone. 526 | Their images I loved, I view in thee, 527 | And thou (all they) hast all the all of me. 528 | 529 | 32 530 | 531 | If thou survive my well-contented day, 532 | When that churl death my bones with dust shall cover 533 | And shalt by fortune once more re-survey 534 | These poor rude lines of thy deceased lover: 535 | Compare them with the bett’ring of the time, 536 | And though they be outstripped by every pen, 537 | Reserve them for my love, not for their rhyme, 538 | Exceeded by the height of happier men. 539 | O then vouchsafe me but this loving thought, 540 | ’Had my friend’s Muse grown with this growing age, 541 | A dearer birth than this his love had brought 542 | To march in ranks of better equipage: 543 | But since he died and poets better prove, 544 | Theirs for their style I’ll read, his for his love’. 545 | 546 | 33 547 | 548 | Full many a glorious morning have I seen, 549 | Flatter the mountain tops with sovereign eye, 550 | Kissing with golden face the meadows green; 551 | Gilding pale streams with heavenly alchemy: 552 | Anon permit the basest clouds to ride, 553 | With ugly rack on his celestial face, 554 | And from the forlorn world his visage hide 555 | Stealing unseen to west with this disgrace: 556 | Even so my sun one early morn did shine, 557 | With all triumphant splendour on my brow, 558 | But out alack, he was but one hour mine, 559 | The region cloud hath masked him from me now. 560 | Yet him for this, my love no whit disdaineth, 561 | Suns of the world may stain, when heaven’s sun staineth. 562 | 563 | 34 564 | 565 | Why didst thou promise such a beauteous day, 566 | And make me travel forth without my cloak, 567 | To let base clouds o’ertake me in my way, 568 | Hiding thy brav’ry in their rotten smoke? 569 | ’Tis not enough that through the cloud thou break, 570 | To dry the rain on my storm-beaten face, 571 | For no man well of such a salve can speak, 572 | That heals the wound, and cures not the disgrace: 573 | Nor can thy shame give physic to my grief, 574 | Though thou repent, yet I have still the loss, 575 | Th’ offender’s sorrow lends but weak relief 576 | To him that bears the strong offence’s cross. 577 | Ah but those tears are pearl which thy love sheds, 578 | And they are rich, and ransom all ill deeds. 579 | 580 | 35 581 | 582 | No more be grieved at that which thou hast done, 583 | Roses have thorns, and silver fountains mud, 584 | Clouds and eclipses stain both moon and sun, 585 | And loathsome canker lives in sweetest bud. 586 | All men make faults, and even I in this, 587 | Authorizing thy trespass with compare, 588 | My self corrupting salving thy amiss, 589 | Excusing thy sins more than thy sins are: 590 | For to thy sensual fault I bring in sense, 591 | Thy adverse party is thy advocate, 592 | And ’gainst my self a lawful plea commence: 593 | Such civil war is in my love and hate, 594 | That I an accessary needs must be, 595 | To that sweet thief which sourly robs from me. 596 | 597 | 36 598 | 599 | Let me confess that we two must be twain, 600 | Although our undivided loves are one: 601 | So shall those blots that do with me remain, 602 | Without thy help, by me be borne alone. 603 | In our two loves there is but one respect, 604 | Though in our lives a separable spite, 605 | Which though it alter not love’s sole effect, 606 | Yet doth it steal sweet hours from love’s delight. 607 | I may not evermore acknowledge thee, 608 | Lest my bewailed guilt should do thee shame, 609 | Nor thou with public kindness honour me, 610 | Unless thou take that honour from thy name: 611 | But do not so, I love thee in such sort, 612 | As thou being mine, mine is thy good report. 613 | 614 | 37 615 | 616 | As a decrepit father takes delight, 617 | To see his active child do deeds of youth, 618 | So I, made lame by Fortune’s dearest spite 619 | Take all my comfort of thy worth and truth. 620 | For whether beauty, birth, or wealth, or wit, 621 | Or any of these all, or all, or more 622 | Entitled in thy parts, do crowned sit, 623 | I make my love engrafted to this store: 624 | So then I am not lame, poor, nor despised, 625 | Whilst that this shadow doth such substance give, 626 | That I in thy abundance am sufficed, 627 | And by a part of all thy glory live: 628 | Look what is best, that best I wish in thee, 629 | This wish I have, then ten times happy me. 630 | 631 | 38 632 | 633 | How can my muse want subject to invent 634 | While thou dost breathe that pour’st into my verse, 635 | Thine own sweet argument, too excellent, 636 | For every vulgar paper to rehearse? 637 | O give thy self the thanks if aught in me, 638 | Worthy perusal stand against thy sight, 639 | For who’s so dumb that cannot write to thee, 640 | When thou thy self dost give invention light? 641 | Be thou the tenth Muse, ten times more in worth 642 | Than those old nine which rhymers invocate, 643 | And he that calls on thee, let him bring forth 644 | Eternal numbers to outlive long date. 645 | If my slight muse do please these curious days, 646 | The pain be mine, but thine shall be the praise. 647 | 648 | 39 649 | 650 | O how thy worth with manners may I sing, 651 | When thou art all the better part of me? 652 | What can mine own praise to mine own self bring: 653 | And what is’t but mine own when I praise thee? 654 | Even for this, let us divided live, 655 | And our dear love lose name of single one, 656 | That by this separation I may give: 657 | That due to thee which thou deserv’st alone: 658 | O absence what a torment wouldst thou prove, 659 | Were it not thy sour leisure gave sweet leave, 660 | To entertain the time with thoughts of love, 661 | Which time and thoughts so sweetly doth deceive. 662 | And that thou teachest how to make one twain, 663 | By praising him here who doth hence remain. 664 | 665 | 40 666 | 667 | Take all my loves, my love, yea take them all, 668 | What hast thou then more than thou hadst before? 669 | No love, my love, that thou mayst true love call, 670 | All mine was thine, before thou hadst this more: 671 | Then if for my love, thou my love receivest, 672 | I cannot blame thee, for my love thou usest, 673 | But yet be blamed, if thou thy self deceivest 674 | By wilful taste of what thy self refusest. 675 | I do forgive thy robbery gentle thief 676 | Although thou steal thee all my poverty: 677 | And yet love knows it is a greater grief 678 | To bear greater wrong, than hate’s known injury. 679 | Lascivious grace, in whom all ill well shows, 680 | Kill me with spites yet we must not be foes. 681 | 682 | 41 683 | 684 | Those pretty wrongs that liberty commits, 685 | When I am sometime absent from thy heart, 686 | Thy beauty, and thy years full well befits, 687 | For still temptation follows where thou art. 688 | Gentle thou art, and therefore to be won, 689 | Beauteous thou art, therefore to be assailed. 690 | And when a woman woos, what woman’s son, 691 | Will sourly leave her till he have prevailed? 692 | Ay me, but yet thou mightst my seat forbear, 693 | And chide thy beauty, and thy straying youth, 694 | Who lead thee in their riot even there 695 | Where thou art forced to break a twofold truth: 696 | Hers by thy beauty tempting her to thee, 697 | Thine by thy beauty being false to me. 698 | 699 | 42 700 | 701 | That thou hast her it is not all my grief, 702 | And yet it may be said I loved her dearly, 703 | That she hath thee is of my wailing chief, 704 | A loss in love that touches me more nearly. 705 | Loving offenders thus I will excuse ye, 706 | Thou dost love her, because thou know’st I love her, 707 | And for my sake even so doth she abuse me, 708 | Suff’ring my friend for my sake to approve her. 709 | If I lose thee, my loss is my love’s gain, 710 | And losing her, my friend hath found that loss, 711 | Both find each other, and I lose both twain, 712 | And both for my sake lay on me this cross, 713 | But here’s the joy, my friend and I are one, 714 | Sweet flattery, then she loves but me alone. 715 | 716 | 43 717 | 718 | When most I wink then do mine eyes best see, 719 | For all the day they view things unrespected, 720 | But when I sleep, in dreams they look on thee, 721 | And darkly bright, are bright in dark directed. 722 | Then thou whose shadow shadows doth make bright 723 | How would thy shadow’s form, form happy show, 724 | To the clear day with thy much clearer light, 725 | When to unseeing eyes thy shade shines so! 726 | How would (I say) mine eyes be blessed made, 727 | By looking on thee in the living day, 728 | When in dead night thy fair imperfect shade, 729 | Through heavy sleep on sightless eyes doth stay! 730 | All days are nights to see till I see thee, 731 | And nights bright days when dreams do show thee me. 732 | 733 | 44 734 | 735 | If the dull substance of my flesh were thought, 736 | Injurious distance should not stop my way, 737 | For then despite of space I would be brought, 738 | From limits far remote, where thou dost stay, 739 | No matter then although my foot did stand 740 | Upon the farthest earth removed from thee, 741 | For nimble thought can jump both sea and land, 742 | As soon as think the place where he would be. 743 | But ah, thought kills me that I am not thought 744 | To leap large lengths of miles when thou art gone, 745 | But that so much of earth and water wrought, 746 | I must attend, time’s leisure with my moan. 747 | Receiving nought by elements so slow, 748 | But heavy tears, badges of either’s woe. 749 | 750 | 45 751 | 752 | The other two, slight air, and purging fire, 753 | Are both with thee, wherever I abide, 754 | The first my thought, the other my desire, 755 | These present-absent with swift motion slide. 756 | For when these quicker elements are gone 757 | In tender embassy of love to thee, 758 | My life being made of four, with two alone, 759 | Sinks down to death, oppressed with melancholy. 760 | Until life’s composition be recured, 761 | By those swift messengers returned from thee, 762 | Who even but now come back again assured, 763 | Of thy fair health, recounting it to me. 764 | This told, I joy, but then no longer glad, 765 | I send them back again and straight grow sad. 766 | 767 | 46 768 | 769 | Mine eye and heart are at a mortal war, 770 | How to divide the conquest of thy sight, 771 | Mine eye, my heart thy picture’s sight would bar, 772 | My heart, mine eye the freedom of that right, 773 | My heart doth plead that thou in him dost lie, 774 | (A closet never pierced with crystal eyes) 775 | But the defendant doth that plea deny, 776 | And says in him thy fair appearance lies. 777 | To side this title is impanelled 778 | A quest of thoughts, all tenants to the heart, 779 | And by their verdict is determined 780 | The clear eye’s moiety, and the dear heart’s part. 781 | As thus, mine eye’s due is thy outward part, 782 | And my heart’s right, thy inward love of heart. 783 | 784 | 47 785 | 786 | Betwixt mine eye and heart a league is took, 787 | And each doth good turns now unto the other, 788 | When that mine eye is famished for a look, 789 | Or heart in love with sighs himself doth smother; 790 | With my love’s picture then my eye doth feast, 791 | And to the painted banquet bids my heart: 792 | Another time mine eye is my heart’s guest, 793 | And in his thoughts of love doth share a part. 794 | So either by thy picture or my love, 795 | Thy self away, art present still with me, 796 | For thou not farther than my thoughts canst move, 797 | And I am still with them, and they with thee. 798 | Or if they sleep, thy picture in my sight 799 | Awakes my heart, to heart’s and eye’s delight. 800 | 801 | 48 802 | 803 | How careful was I when I took my way, 804 | Each trifle under truest bars to thrust, 805 | That to my use it might unused stay 806 | From hands of falsehood, in sure wards of trust! 807 | But thou, to whom my jewels trifles are, 808 | Most worthy comfort, now my greatest grief, 809 | Thou best of dearest, and mine only care, 810 | Art left the prey of every vulgar thief. 811 | Thee have I not locked up in any chest, 812 | Save where thou art not, though I feel thou art, 813 | Within the gentle closure of my breast, 814 | From whence at pleasure thou mayst come and part, 815 | And even thence thou wilt be stol’n I fear, 816 | For truth proves thievish for a prize so dear. 817 | 818 | 49 819 | 820 | Against that time (if ever that time come) 821 | When I shall see thee frown on my defects, 822 | When as thy love hath cast his utmost sum, 823 | Called to that audit by advised respects, 824 | Against that time when thou shalt strangely pass, 825 | And scarcely greet me with that sun thine eye, 826 | When love converted from the thing it was 827 | Shall reasons find of settled gravity; 828 | Against that time do I ensconce me here 829 | Within the knowledge of mine own desert, 830 | And this my hand, against my self uprear, 831 | To guard the lawful reasons on thy part, 832 | To leave poor me, thou hast the strength of laws, 833 | Since why to love, I can allege no cause. 834 | 835 | 50 836 | 837 | How heavy do I journey on the way, 838 | When what I seek (my weary travel’s end) 839 | Doth teach that case and that repose to say 840 | ’Thus far the miles are measured from thy friend.’ 841 | The beast that bears me, tired with my woe, 842 | Plods dully on, to bear that weight in me, 843 | As if by some instinct the wretch did know 844 | His rider loved not speed being made from thee: 845 | The bloody spur cannot provoke him on, 846 | That sometimes anger thrusts into his hide, 847 | Which heavily he answers with a groan, 848 | More sharp to me than spurring to his side, 849 | For that same groan doth put this in my mind, 850 | My grief lies onward and my joy behind. 851 | 852 | 51 853 | 854 | Thus can my love excuse the slow offence, 855 | Of my dull bearer, when from thee I speed, 856 | From where thou art, why should I haste me thence? 857 | Till I return of posting is no need. 858 | O what excuse will my poor beast then find, 859 | When swift extremity can seem but slow? 860 | Then should I spur though mounted on the wind, 861 | In winged speed no motion shall I know, 862 | Then can no horse with my desire keep pace, 863 | Therefore desire (of perfect’st love being made) 864 | Shall neigh (no dull flesh) in his fiery race, 865 | But love, for love, thus shall excuse my jade, 866 | Since from thee going, he went wilful-slow, 867 | Towards thee I’ll run, and give him leave to go. 868 | 869 | 52 870 | 871 | So am I as the rich whose blessed key, 872 | Can bring him to his sweet up-locked treasure, 873 | The which he will not every hour survey, 874 | For blunting the fine point of seldom pleasure. 875 | Therefore are feasts so solemn and so rare, 876 | Since seldom coming in that long year set, 877 | Like stones of worth they thinly placed are, 878 | Or captain jewels in the carcanet. 879 | So is the time that keeps you as my chest 880 | Or as the wardrobe which the robe doth hide, 881 | To make some special instant special-blest, 882 | By new unfolding his imprisoned pride. 883 | Blessed are you whose worthiness gives scope, 884 | Being had to triumph, being lacked to hope. 885 | 886 | 53 887 | 888 | What is your substance, whereof are you made, 889 | That millions of strange shadows on you tend? 890 | Since every one, hath every one, one shade, 891 | And you but one, can every shadow lend: 892 | Describe Adonis and the counterfeit, 893 | Is poorly imitated after you, 894 | On Helen’s cheek all art of beauty set, 895 | And you in Grecian tires are painted new: 896 | Speak of the spring, and foison of the year, 897 | The one doth shadow of your beauty show, 898 | The other as your bounty doth appear, 899 | And you in every blessed shape we know. 900 | In all external grace you have some part, 901 | But you like none, none you for constant heart. 902 | 903 | 54 904 | 905 | O how much more doth beauty beauteous seem, 906 | By that sweet ornament which truth doth give! 907 | The rose looks fair, but fairer we it deem 908 | For that sweet odour, which doth in it live: 909 | The canker blooms have full as deep a dye, 910 | As the perfumed tincture of the roses, 911 | Hang on such thorns, and play as wantonly, 912 | When summer’s breath their masked buds discloses: 913 | But for their virtue only is their show, 914 | They live unwooed, and unrespected fade, 915 | Die to themselves. Sweet roses do not so, 916 | Of their sweet deaths, are sweetest odours made: 917 | And so of you, beauteous and lovely youth, 918 | When that shall fade, my verse distills your truth. 919 | 920 | 55 921 | 922 | Not marble, nor the gilded monuments 923 | Of princes shall outlive this powerful rhyme, 924 | But you shall shine more bright in these contents 925 | Than unswept stone, besmeared with sluttish time. 926 | When wasteful war shall statues overturn, 927 | And broils root out the work of masonry, 928 | Nor Mars his sword, nor war’s quick fire shall burn: 929 | The living record of your memory. 930 | ’Gainst death, and all-oblivious enmity 931 | Shall you pace forth, your praise shall still find room, 932 | Even in the eyes of all posterity 933 | That wear this world out to the ending doom. 934 | So till the judgment that your self arise, 935 | You live in this, and dwell in lovers’ eyes. 936 | 937 | 56 938 | 939 | Sweet love renew thy force, be it not said 940 | Thy edge should blunter be than appetite, 941 | Which but to-day by feeding is allayed, 942 | To-morrow sharpened in his former might. 943 | So love be thou, although to-day thou fill 944 | Thy hungry eyes, even till they wink with fulness, 945 | To-morrow see again, and do not kill 946 | The spirit of love, with a perpetual dulness: 947 | Let this sad interim like the ocean be 948 | Which parts the shore, where two contracted new, 949 | Come daily to the banks, that when they see: 950 | Return of love, more blest may be the view. 951 | Or call it winter, which being full of care, 952 | Makes summer’s welcome, thrice more wished, more rare. 953 | 954 | 57 955 | 956 | Being your slave what should I do but tend, 957 | Upon the hours, and times of your desire? 958 | I have no precious time at all to spend; 959 | Nor services to do till you require. 960 | Nor dare I chide the world-without-end hour, 961 | Whilst I (my sovereign) watch the clock for you, 962 | Nor think the bitterness of absence sour, 963 | When you have bid your servant once adieu. 964 | Nor dare I question with my jealous thought, 965 | Where you may be, or your affairs suppose, 966 | But like a sad slave stay and think of nought 967 | Save where you are, how happy you make those. 968 | So true a fool is love, that in your will, 969 | (Though you do any thing) he thinks no ill. 970 | 971 | 58 972 | 973 | That god forbid, that made me first your slave, 974 | I should in thought control your times of pleasure, 975 | Or at your hand th’ account of hours to crave, 976 | Being your vassal bound to stay your leisure. 977 | O let me suffer (being at your beck) 978 | Th’ imprisoned absence of your liberty, 979 | And patience tame to sufferance bide each check, 980 | Without accusing you of injury. 981 | Be where you list, your charter is so strong, 982 | That you your self may privilage your time 983 | To what you will, to you it doth belong, 984 | Your self to pardon of self-doing crime. 985 | I am to wait, though waiting so be hell, 986 | Not blame your pleasure be it ill or well. 987 | 988 | 59 989 | 990 | If there be nothing new, but that which is, 991 | Hath been before, how are our brains beguiled, 992 | Which labouring for invention bear amis 993 | The second burthen of a former child! 994 | O that record could with a backward look, 995 | Even of five hundred courses of the sun, 996 | Show me your image in some antique book, 997 | Since mind at first in character was done. 998 | That I might see what the old world could say, 999 | To this composed wonder of your frame, 1000 | Whether we are mended, or whether better they, 1001 | Or whether revolution be the same. 1002 | O sure I am the wits of former days, 1003 | To subjects worse have given admiring praise. 1004 | 1005 | 60 1006 | 1007 | Like as the waves make towards the pebbled shore, 1008 | So do our minutes hasten to their end, 1009 | Each changing place with that which goes before, 1010 | In sequent toil all forwards do contend. 1011 | Nativity once in the main of light, 1012 | Crawls to maturity, wherewith being crowned, 1013 | Crooked eclipses ’gainst his glory fight, 1014 | And Time that gave, doth now his gift confound. 1015 | Time doth transfix the flourish set on youth, 1016 | And delves the parallels in beauty’s brow, 1017 | Feeds on the rarities of nature’s truth, 1018 | And nothing stands but for his scythe to mow. 1019 | And yet to times in hope, my verse shall stand 1020 | Praising thy worth, despite his cruel hand. 1021 | 1022 | 61 1023 | 1024 | Is it thy will, thy image should keep open 1025 | My heavy eyelids to the weary night? 1026 | Dost thou desire my slumbers should be broken, 1027 | While shadows like to thee do mock my sight? 1028 | Is it thy spirit that thou send’st from thee 1029 | So far from home into my deeds to pry, 1030 | To find out shames and idle hours in me, 1031 | The scope and tenure of thy jealousy? 1032 | O no, thy love though much, is not so great, 1033 | It is my love that keeps mine eye awake, 1034 | Mine own true love that doth my rest defeat, 1035 | To play the watchman ever for thy sake. 1036 | For thee watch I, whilst thou dost wake elsewhere, 1037 | From me far off, with others all too near. 1038 | 1039 | 62 1040 | 1041 | Sin of self-love possesseth all mine eye, 1042 | And all my soul, and all my every part; 1043 | And for this sin there is no remedy, 1044 | It is so grounded inward in my heart. 1045 | Methinks no face so gracious is as mine, 1046 | No shape so true, no truth of such account, 1047 | And for my self mine own worth do define, 1048 | As I all other in all worths surmount. 1049 | But when my glass shows me my self indeed 1050 | beated and chopt with tanned antiquity, 1051 | Mine own self-love quite contrary I read: 1052 | Self, so self-loving were iniquity. 1053 | ’Tis thee (my self) that for my self I praise, 1054 | Painting my age with beauty of thy days. 1055 | 1056 | 63 1057 | 1058 | Against my love shall be as I am now 1059 | With Time’s injurious hand crushed and o’erworn, 1060 | When hours have drained his blood and filled his brow 1061 | With lines and wrinkles, when his youthful morn 1062 | Hath travelled on to age’s steepy night, 1063 | And all those beauties whereof now he’s king 1064 | Are vanishing, or vanished out of sight, 1065 | Stealing away the treasure of his spring: 1066 | For such a time do I now fortify 1067 | Against confounding age’s cruel knife, 1068 | That he shall never cut from memory 1069 | My sweet love’s beauty, though my lover’s life. 1070 | His beauty shall in these black lines be seen, 1071 | And they shall live, and he in them still green. 1072 | 1073 | 64 1074 | 1075 | When I have seen by Time’s fell hand defaced 1076 | The rich-proud cost of outworn buried age, 1077 | When sometime lofty towers I see down-rased, 1078 | And brass eternal slave to mortal rage. 1079 | When I have seen the hungry ocean gain 1080 | Advantage on the kingdom of the shore, 1081 | And the firm soil win of the watery main, 1082 | Increasing store with loss, and loss with store. 1083 | When I have seen such interchange of State, 1084 | Or state it self confounded, to decay, 1085 | Ruin hath taught me thus to ruminate 1086 | That Time will come and take my love away. 1087 | This thought is as a death which cannot choose 1088 | But weep to have, that which it fears to lose. 1089 | 1090 | 65 1091 | 1092 | Since brass, nor stone, nor earth, nor boundless sea, 1093 | But sad mortality o’ersways their power, 1094 | How with this rage shall beauty hold a plea, 1095 | Whose action is no stronger than a flower? 1096 | O how shall summer’s honey breath hold out, 1097 | Against the wrackful siege of batt’ring days, 1098 | When rocks impregnable are not so stout, 1099 | Nor gates of steel so strong but time decays? 1100 | O fearful meditation, where alack, 1101 | Shall Time’s best jewel from Time’s chest lie hid? 1102 | Or what strong hand can hold his swift foot back, 1103 | Or who his spoil of beauty can forbid? 1104 | O none, unless this miracle have might, 1105 | That in black ink my love may still shine bright. 1106 | 1107 | 66 1108 | 1109 | Tired with all these for restful death I cry, 1110 | As to behold desert a beggar born, 1111 | And needy nothing trimmed in jollity, 1112 | And purest faith unhappily forsworn, 1113 | And gilded honour shamefully misplaced, 1114 | And maiden virtue rudely strumpeted, 1115 | And right perfection wrongfully disgraced, 1116 | And strength by limping sway disabled 1117 | And art made tongue-tied by authority, 1118 | And folly (doctor-like) controlling skill, 1119 | And simple truth miscalled simplicity, 1120 | And captive good attending captain ill. 1121 | Tired with all these, from these would I be gone, 1122 | Save that to die, I leave my love alone. 1123 | 1124 | 67 1125 | 1126 | Ah wherefore with infection should he live, 1127 | And with his presence grace impiety, 1128 | That sin by him advantage should achieve, 1129 | And lace it self with his society? 1130 | Why should false painting imitate his cheek, 1131 | And steal dead seeming of his living hue? 1132 | Why should poor beauty indirectly seek, 1133 | Roses of shadow, since his rose is true? 1134 | Why should he live, now nature bankrupt is, 1135 | Beggared of blood to blush through lively veins, 1136 | For she hath no exchequer now but his, 1137 | And proud of many, lives upon his gains? 1138 | O him she stores, to show what wealth she had, 1139 | In days long since, before these last so bad. 1140 | 1141 | 68 1142 | 1143 | Thus is his cheek the map of days outworn, 1144 | When beauty lived and died as flowers do now, 1145 | Before these bastard signs of fair were born, 1146 | Or durst inhabit on a living brow: 1147 | Before the golden tresses of the dead, 1148 | The right of sepulchres, were shorn away, 1149 | To live a second life on second head, 1150 | Ere beauty’s dead fleece made another gay: 1151 | In him those holy antique hours are seen, 1152 | Without all ornament, it self and true, 1153 | Making no summer of another’s green, 1154 | Robbing no old to dress his beauty new, 1155 | And him as for a map doth Nature store, 1156 | To show false Art what beauty was of yore. 1157 | 1158 | 69 1159 | 1160 | Those parts of thee that the world’s eye doth view, 1161 | Want nothing that the thought of hearts can mend: 1162 | All tongues (the voice of souls) give thee that due, 1163 | Uttering bare truth, even so as foes commend. 1164 | Thy outward thus with outward praise is crowned, 1165 | But those same tongues that give thee so thine own, 1166 | In other accents do this praise confound 1167 | By seeing farther than the eye hath shown. 1168 | They look into the beauty of thy mind, 1169 | And that in guess they measure by thy deeds, 1170 | Then churls their thoughts (although their eyes were kind) 1171 | To thy fair flower add the rank smell of weeds: 1172 | But why thy odour matcheth not thy show, 1173 | The soil is this, that thou dost common grow. 1174 | 1175 | 70 1176 | 1177 | That thou art blamed shall not be thy defect, 1178 | For slander’s mark was ever yet the fair, 1179 | The ornament of beauty is suspect, 1180 | A crow that flies in heaven’s sweetest air. 1181 | So thou be good, slander doth but approve, 1182 | Thy worth the greater being wooed of time, 1183 | For canker vice the sweetest buds doth love, 1184 | And thou present’st a pure unstained prime. 1185 | Thou hast passed by the ambush of young days, 1186 | Either not assailed, or victor being charged, 1187 | Yet this thy praise cannot be so thy praise, 1188 | To tie up envy, evermore enlarged, 1189 | If some suspect of ill masked not thy show, 1190 | Then thou alone kingdoms of hearts shouldst owe. 1191 | 1192 | 71 1193 | 1194 | No longer mourn for me when I am dead, 1195 | Than you shall hear the surly sullen bell 1196 | Give warning to the world that I am fled 1197 | From this vile world with vilest worms to dwell: 1198 | Nay if you read this line, remember not, 1199 | The hand that writ it, for I love you so, 1200 | That I in your sweet thoughts would be forgot, 1201 | If thinking on me then should make you woe. 1202 | O if (I say) you look upon this verse, 1203 | When I (perhaps) compounded am with clay, 1204 | Do not so much as my poor name rehearse; 1205 | But let your love even with my life decay. 1206 | Lest the wise world should look into your moan, 1207 | And mock you with me after I am gone. 1208 | 1209 | 72 1210 | 1211 | O lest the world should task you to recite, 1212 | What merit lived in me that you should love 1213 | After my death (dear love) forget me quite, 1214 | For you in me can nothing worthy prove. 1215 | Unless you would devise some virtuous lie, 1216 | To do more for me than mine own desert, 1217 | And hang more praise upon deceased I, 1218 | Than niggard truth would willingly impart: 1219 | O lest your true love may seem false in this, 1220 | That you for love speak well of me untrue, 1221 | My name be buried where my body is, 1222 | And live no more to shame nor me, nor you. 1223 | For I am shamed by that which I bring forth, 1224 | And so should you, to love things nothing worth. 1225 | 1226 | 73 1227 | 1228 | That time of year thou mayst in me behold, 1229 | When yellow leaves, or none, or few do hang 1230 | Upon those boughs which shake against the cold, 1231 | Bare ruined choirs, where late the sweet birds sang. 1232 | In me thou seest the twilight of such day, 1233 | As after sunset fadeth in the west, 1234 | Which by and by black night doth take away, 1235 | Death’s second self that seals up all in rest. 1236 | In me thou seest the glowing of such fire, 1237 | That on the ashes of his youth doth lie, 1238 | As the death-bed, whereon it must expire, 1239 | Consumed with that which it was nourished by. 1240 | This thou perceiv’st, which makes thy love more strong, 1241 | To love that well, which thou must leave ere long. 1242 | 1243 | 74 1244 | 1245 | But be contented when that fell arrest, 1246 | Without all bail shall carry me away, 1247 | My life hath in this line some interest, 1248 | Which for memorial still with thee shall stay. 1249 | When thou reviewest this, thou dost review, 1250 | The very part was consecrate to thee, 1251 | The earth can have but earth, which is his due, 1252 | My spirit is thine the better part of me, 1253 | So then thou hast but lost the dregs of life, 1254 | The prey of worms, my body being dead, 1255 | The coward conquest of a wretch’s knife, 1256 | Too base of thee to be remembered, 1257 | The worth of that, is that which it contains, 1258 | And that is this, and this with thee remains. 1259 | 1260 | 75 1261 | 1262 | So are you to my thoughts as food to life, 1263 | Or as sweet-seasoned showers are to the ground; 1264 | And for the peace of you I hold such strife 1265 | As ’twixt a miser and his wealth is found. 1266 | Now proud as an enjoyer, and anon 1267 | Doubting the filching age will steal his treasure, 1268 | Now counting best to be with you alone, 1269 | Then bettered that the world may see my pleasure, 1270 | Sometime all full with feasting on your sight, 1271 | And by and by clean starved for a look, 1272 | Possessing or pursuing no delight 1273 | Save what is had, or must from you be took. 1274 | Thus do I pine and surfeit day by day, 1275 | Or gluttoning on all, or all away. 1276 | 1277 | 76 1278 | 1279 | Why is my verse so barren of new pride? 1280 | So far from variation or quick change? 1281 | Why with the time do I not glance aside 1282 | To new-found methods, and to compounds strange? 1283 | Why write I still all one, ever the same, 1284 | And keep invention in a noted weed, 1285 | That every word doth almost tell my name, 1286 | Showing their birth, and where they did proceed? 1287 | O know sweet love I always write of you, 1288 | And you and love are still my argument: 1289 | So all my best is dressing old words new, 1290 | Spending again what is already spent: 1291 | For as the sun is daily new and old, 1292 | So is my love still telling what is told. 1293 | 1294 | 77 1295 | 1296 | Thy glass will show thee how thy beauties wear, 1297 | Thy dial how thy precious minutes waste, 1298 | These vacant leaves thy mind’s imprint will bear, 1299 | And of this book, this learning mayst thou taste. 1300 | The wrinkles which thy glass will truly show, 1301 | Of mouthed graves will give thee memory, 1302 | Thou by thy dial’s shady stealth mayst know, 1303 | Time’s thievish progress to eternity. 1304 | Look what thy memory cannot contain, 1305 | Commit to these waste blanks, and thou shalt find 1306 | Those children nursed, delivered from thy brain, 1307 | To take a new acquaintance of thy mind. 1308 | These offices, so oft as thou wilt look, 1309 | Shall profit thee, and much enrich thy book. 1310 | 1311 | 78 1312 | 1313 | So oft have I invoked thee for my muse, 1314 | And found such fair assistance in my verse, 1315 | As every alien pen hath got my use, 1316 | And under thee their poesy disperse. 1317 | Thine eyes, that taught the dumb on high to sing, 1318 | And heavy ignorance aloft to fly, 1319 | Have added feathers to the learned’s wing, 1320 | And given grace a double majesty. 1321 | Yet be most proud of that which I compile, 1322 | Whose influence is thine, and born of thee, 1323 | In others’ works thou dost but mend the style, 1324 | And arts with thy sweet graces graced be. 1325 | But thou art all my art, and dost advance 1326 | As high as learning, my rude ignorance. 1327 | 1328 | 79 1329 | 1330 | Whilst I alone did call upon thy aid, 1331 | My verse alone had all thy gentle grace, 1332 | But now my gracious numbers are decayed, 1333 | And my sick muse doth give an other place. 1334 | I grant (sweet love) thy lovely argument 1335 | Deserves the travail of a worthier pen, 1336 | Yet what of thee thy poet doth invent, 1337 | He robs thee of, and pays it thee again, 1338 | He lends thee virtue, and he stole that word, 1339 | From thy behaviour, beauty doth he give 1340 | And found it in thy cheek: he can afford 1341 | No praise to thee, but what in thee doth live. 1342 | Then thank him not for that which he doth say, 1343 | Since what he owes thee, thou thy self dost pay. 1344 | 1345 | 80 1346 | 1347 | O how I faint when I of you do write, 1348 | Knowing a better spirit doth use your name, 1349 | And in the praise thereof spends all his might, 1350 | To make me tongue-tied speaking of your fame. 1351 | But since your worth (wide as the ocean is) 1352 | The humble as the proudest sail doth bear, 1353 | My saucy bark (inferior far to his) 1354 | On your broad main doth wilfully appear. 1355 | Your shallowest help will hold me up afloat, 1356 | Whilst he upon your soundless deep doth ride, 1357 | Or (being wrecked) I am a worthless boat, 1358 | He of tall building, and of goodly pride. 1359 | Then if he thrive and I be cast away, 1360 | The worst was this, my love was my decay. 1361 | 1362 | 81 1363 | 1364 | Or I shall live your epitaph to make, 1365 | Or you survive when I in earth am rotten, 1366 | From hence your memory death cannot take, 1367 | Although in me each part will be forgotten. 1368 | Your name from hence immortal life shall have, 1369 | Though I (once gone) to all the world must die, 1370 | The earth can yield me but a common grave, 1371 | When you entombed in men’s eyes shall lie, 1372 | Your monument shall be my gentle verse, 1373 | Which eyes not yet created shall o’er-read, 1374 | And tongues to be, your being shall rehearse, 1375 | When all the breathers of this world are dead, 1376 | You still shall live (such virtue hath my pen) 1377 | Where breath most breathes, even in the mouths of men. 1378 | 1379 | 82 1380 | 1381 | I grant thou wert not married to my muse, 1382 | And therefore mayst without attaint o’erlook 1383 | The dedicated words which writers use 1384 | Of their fair subject, blessing every book. 1385 | Thou art as fair in knowledge as in hue, 1386 | Finding thy worth a limit past my praise, 1387 | And therefore art enforced to seek anew, 1388 | Some fresher stamp of the time-bettering days. 1389 | And do so love, yet when they have devised, 1390 | What strained touches rhetoric can lend, 1391 | Thou truly fair, wert truly sympathized, 1392 | In true plain words, by thy true-telling friend. 1393 | And their gross painting might be better used, 1394 | Where cheeks need blood, in thee it is abused. 1395 | 1396 | 83 1397 | 1398 | I never saw that you did painting need, 1399 | And therefore to your fair no painting set, 1400 | I found (or thought I found) you did exceed, 1401 | That barren tender of a poet’s debt: 1402 | And therefore have I slept in your report, 1403 | That you your self being extant well might show, 1404 | How far a modern quill doth come too short, 1405 | Speaking of worth, what worth in you doth grow. 1406 | This silence for my sin you did impute, 1407 | Which shall be most my glory being dumb, 1408 | For I impair not beauty being mute, 1409 | When others would give life, and bring a tomb. 1410 | There lives more life in one of your fair eyes, 1411 | Than both your poets can in praise devise. 1412 | 1413 | 84 1414 | 1415 | Who is it that says most, which can say more, 1416 | Than this rich praise, that you alone, are you? 1417 | In whose confine immured is the store, 1418 | Which should example where your equal grew. 1419 | Lean penury within that pen doth dwell, 1420 | That to his subject lends not some small glory, 1421 | But he that writes of you, if he can tell, 1422 | That you are you, so dignifies his story. 1423 | Let him but copy what in you is writ, 1424 | Not making worse what nature made so clear, 1425 | And such a counterpart shall fame his wit, 1426 | Making his style admired every where. 1427 | You to your beauteous blessings add a curse, 1428 | Being fond on praise, which makes your praises worse. 1429 | 1430 | 85 1431 | 1432 | My tongue-tied muse in manners holds her still, 1433 | While comments of your praise richly compiled, 1434 | Reserve their character with golden quill, 1435 | And precious phrase by all the Muses filed. 1436 | I think good thoughts, whilst other write good words, 1437 | And like unlettered clerk still cry Amen, 1438 | To every hymn that able spirit affords, 1439 | In polished form of well refined pen. 1440 | Hearing you praised, I say ’tis so, ’tis true, 1441 | And to the most of praise add something more, 1442 | But that is in my thought, whose love to you 1443 | (Though words come hindmost) holds his rank before, 1444 | Then others, for the breath of words respect, 1445 | Me for my dumb thoughts, speaking in effect. 1446 | 1447 | 86 1448 | 1449 | Was it the proud full sail of his great verse, 1450 | Bound for the prize of (all too precious) you, 1451 | That did my ripe thoughts in my brain inhearse, 1452 | Making their tomb the womb wherein they grew? 1453 | Was it his spirit, by spirits taught to write, 1454 | Above a mortal pitch, that struck me dead? 1455 | No, neither he, nor his compeers by night 1456 | Giving him aid, my verse astonished. 1457 | He nor that affable familiar ghost 1458 | Which nightly gulls him with intelligence, 1459 | As victors of my silence cannot boast, 1460 | I was not sick of any fear from thence. 1461 | But when your countenance filled up his line, 1462 | Then lacked I matter, that enfeebled mine. 1463 | 1464 | 87 1465 | 1466 | Farewell! thou art too dear for my possessing, 1467 | And like enough thou know’st thy estimate, 1468 | The charter of thy worth gives thee releasing: 1469 | My bonds in thee are all determinate. 1470 | For how do I hold thee but by thy granting, 1471 | And for that riches where is my deserving? 1472 | The cause of this fair gift in me is wanting, 1473 | And so my patent back again is swerving. 1474 | Thy self thou gav’st, thy own worth then not knowing, 1475 | Or me to whom thou gav’st it, else mistaking, 1476 | So thy great gift upon misprision growing, 1477 | Comes home again, on better judgement making. 1478 | Thus have I had thee as a dream doth flatter, 1479 | In sleep a king, but waking no such matter. 1480 | 1481 | 88 1482 | 1483 | When thou shalt be disposed to set me light, 1484 | And place my merit in the eye of scorn, 1485 | Upon thy side, against my self I’ll fight, 1486 | And prove thee virtuous, though thou art forsworn: 1487 | With mine own weakness being best acquainted, 1488 | Upon thy part I can set down a story 1489 | Of faults concealed, wherein I am attainted: 1490 | That thou in losing me, shalt win much glory: 1491 | And I by this will be a gainer too, 1492 | For bending all my loving thoughts on thee, 1493 | The injuries that to my self I do, 1494 | Doing thee vantage, double-vantage me. 1495 | Such is my love, to thee I so belong, 1496 | That for thy right, my self will bear all wrong. 1497 | 1498 | 89 1499 | 1500 | Say that thou didst forsake me for some fault, 1501 | And I will comment upon that offence, 1502 | Speak of my lameness, and I straight will halt: 1503 | Against thy reasons making no defence. 1504 | Thou canst not (love) disgrace me half so ill, 1505 | To set a form upon desired change, 1506 | As I’ll my self disgrace, knowing thy will, 1507 | I will acquaintance strangle and look strange: 1508 | Be absent from thy walks and in my tongue, 1509 | Thy sweet beloved name no more shall dwell, 1510 | Lest I (too much profane) should do it wronk: 1511 | And haply of our old acquaintance tell. 1512 | For thee, against my self I’ll vow debate, 1513 | For I must ne’er love him whom thou dost hate. 1514 | 1515 | 90 1516 | 1517 | Then hate me when thou wilt, if ever, now, 1518 | Now while the world is bent my deeds to cross, 1519 | join with the spite of fortune, make me bow, 1520 | And do not drop in for an after-loss: 1521 | Ah do not, when my heart hath ’scaped this sorrow, 1522 | Come in the rearward of a conquered woe, 1523 | Give not a windy night a rainy morrow, 1524 | To linger out a purposed overthrow. 1525 | If thou wilt leave me, do not leave me last, 1526 | When other petty griefs have done their spite, 1527 | But in the onset come, so shall I taste 1528 | At first the very worst of fortune’s might. 1529 | And other strains of woe, which now seem woe, 1530 | Compared with loss of thee, will not seem so. 1531 | 1532 | 91 1533 | 1534 | Some glory in their birth, some in their skill, 1535 | Some in their wealth, some in their body’s force, 1536 | Some in their garments though new-fangled ill: 1537 | Some in their hawks and hounds, some in their horse. 1538 | And every humour hath his adjunct pleasure, 1539 | Wherein it finds a joy above the rest, 1540 | But these particulars are not my measure, 1541 | All these I better in one general best. 1542 | Thy love is better than high birth to me, 1543 | Richer than wealth, prouder than garments’ costs, 1544 | Of more delight than hawks and horses be: 1545 | And having thee, of all men’s pride I boast. 1546 | Wretched in this alone, that thou mayst take, 1547 | All this away, and me most wretchcd make. 1548 | 1549 | 92 1550 | 1551 | But do thy worst to steal thy self away, 1552 | For term of life thou art assured mine, 1553 | And life no longer than thy love will stay, 1554 | For it depends upon that love of thine. 1555 | Then need I not to fear the worst of wrongs, 1556 | When in the least of them my life hath end, 1557 | I see, a better state to me belongs 1558 | Than that, which on thy humour doth depend. 1559 | Thou canst not vex me with inconstant mind, 1560 | Since that my life on thy revolt doth lie, 1561 | O what a happy title do I find, 1562 | Happy to have thy love, happy to die! 1563 | But what’s so blessed-fair that fears no blot? 1564 | Thou mayst be false, and yet I know it not. 1565 | 1566 | 93 1567 | 1568 | So shall I live, supposing thou art true, 1569 | Like a deceived husband, so love’s face, 1570 | May still seem love to me, though altered new: 1571 | Thy looks with me, thy heart in other place. 1572 | For there can live no hatred in thine eye, 1573 | Therefore in that I cannot know thy change, 1574 | In many’s looks, the false heart’s history 1575 | Is writ in moods and frowns and wrinkles strange. 1576 | But heaven in thy creation did decree, 1577 | That in thy face sweet love should ever dwell, 1578 | Whate’er thy thoughts, or thy heart’s workings be, 1579 | Thy looks should nothing thence, but sweetness tell. 1580 | How like Eve’s apple doth thy beauty grow, 1581 | If thy sweet virtue answer not thy show. 1582 | 1583 | 94 1584 | 1585 | They that have power to hurt, and will do none, 1586 | That do not do the thing, they most do show, 1587 | Who moving others, are themselves as stone, 1588 | Unmoved, cold, and to temptation slow: 1589 | They rightly do inherit heaven’s graces, 1590 | And husband nature’s riches from expense, 1591 | Tibey are the lords and owners of their faces, 1592 | Others, but stewards of their excellence: 1593 | The summer’s flower is to the summer sweet, 1594 | Though to it self, it only live and die, 1595 | But if that flower with base infection meet, 1596 | The basest weed outbraves his dignity: 1597 | For sweetest things turn sourest by their deeds, 1598 | Lilies that fester, smell far worse than weeds. 1599 | 1600 | 95 1601 | 1602 | How sweet and lovely dost thou make the shame, 1603 | Which like a canker in the fragrant rose, 1604 | Doth spot the beauty of thy budding name! 1605 | O in what sweets dost thou thy sins enclose! 1606 | That tongue that tells the story of thy days, 1607 | (Making lascivious comments on thy sport) 1608 | Cannot dispraise, but in a kind of praise, 1609 | Naming thy name, blesses an ill report. 1610 | O what a mansion have those vices got, 1611 | Which for their habitation chose out thee, 1612 | Where beauty’s veil doth cover every blot, 1613 | And all things turns to fair, that eyes can see! 1614 | Take heed (dear heart) of this large privilege, 1615 | The hardest knife ill-used doth lose his edge. 1616 | 1617 | 96 1618 | 1619 | Some say thy fault is youth, some wantonness, 1620 | Some say thy grace is youth and gentle sport, 1621 | Both grace and faults are loved of more and less: 1622 | Thou mak’st faults graces, that to thee resort: 1623 | As on the finger of a throned queen, 1624 | The basest jewel will be well esteemed: 1625 | So are those errors that in thee are seen, 1626 | To truths translated, and for true things deemed. 1627 | How many lambs might the stern wolf betray, 1628 | If like a lamb he could his looks translate! 1629 | How many gazers mightst thou lead away, 1630 | if thou wouldst use the strength of all thy state! 1631 | But do not so, I love thee in such sort, 1632 | As thou being mine, mine is thy good report. 1633 | 1634 | 97 1635 | 1636 | How like a winter hath my absence been 1637 | From thee, the pleasure of the fleeting year! 1638 | What freezings have I felt, what dark days seen! 1639 | What old December’s bareness everywhere! 1640 | And yet this time removed was summer’s time, 1641 | The teeming autumn big with rich increase, 1642 | Bearing the wanton burden of the prime, 1643 | Like widowed wombs after their lords’ decease: 1644 | Yet this abundant issue seemed to me 1645 | But hope of orphans, and unfathered fruit, 1646 | For summer and his pleasures wait on thee, 1647 | And thou away, the very birds are mute. 1648 | Or if they sing, ’tis with so dull a cheer, 1649 | That leaves look pale, dreading the winter’s near. 1650 | 1651 | 98 1652 | 1653 | From you have I been absent in the spring, 1654 | When proud-pied April (dressed in all his trim) 1655 | Hath put a spirit of youth in every thing: 1656 | That heavy Saturn laughed and leaped with him. 1657 | Yet nor the lays of birds, nor the sweet smell 1658 | Of different flowers in odour and in hue, 1659 | Could make me any summer’s story tell: 1660 | Or from their proud lap pluck them where they grew: 1661 | Nor did I wonder at the lily’s white, 1662 | Nor praise the deep vermilion in the rose, 1663 | They were but sweet, but figures of delight: 1664 | Drawn after you, you pattern of all those. 1665 | Yet seemed it winter still, and you away, 1666 | As with your shadow I with these did play. 1667 | 1668 | 99 1669 | 1670 | The forward violet thus did I chide, 1671 | Sweet thief, whence didst thou steal thy sweet that smells, 1672 | If not from my love’s breath? The purple pride 1673 | Which on thy soft check for complexion dwells, 1674 | In my love’s veins thou hast too grossly dyed. 1675 | The lily I condemned for thy hand, 1676 | And buds of marjoram had stol’n thy hair, 1677 | The roses fearfully on thorns did stand, 1678 | One blushing shame, another white despair: 1679 | A third nor red, nor white, had stol’n of both, 1680 | And to his robbery had annexed thy breath, 1681 | But for his theft in pride of all his growth 1682 | A vengeful canker eat him up to death. 1683 | More flowers I noted, yet I none could see, 1684 | But sweet, or colour it had stol’n from thee. -------------------------------------------------------------------------------- /test/zip-aes.js: -------------------------------------------------------------------------------- 1 | const archiver = require('archiver'); 2 | const fs = require('fs'); 3 | const cp = require('child_process'); 4 | const rmrf = require('rimraf'); 5 | const should = require('should'); 6 | const path = require('path'); 7 | const lazystream = require('lazystream'); 8 | 9 | /** 10 | * This test assumes 7-Zip installed in the system and available in path 11 | */ 12 | describe('zip-aes', () => { 13 | before(() => { 14 | try { 15 | archiver.registerFormat('zip-encrypted', require('../')); 16 | } catch (e) { 17 | // already registered 18 | } 19 | }); 20 | 21 | beforeEach(() => { 22 | rmrf.sync('./target'); 23 | fs.mkdirSync('./target', {recursive: true}); 24 | }); 25 | 26 | it('should pack with zip-aes and unpack with 7z', (done) => { 27 | let archive = archiver.create('zip-encrypted', {zlib: {level: 8}, encryptionMethod: 'aes256', password: '123'}); 28 | archive.append(fs.createReadStream('./test/resources/test.txt'), { // with stream 29 | name: 'test.txt' 30 | }); 31 | archive.append(fs.createReadStream('./test/resources/test.txt'), { // with buffer 32 | name: 'test2.txt' 33 | }); 34 | archive.append('./test/resources/test.txt', { // file path 35 | name: 'test3.txt' 36 | }); 37 | archive.append(new lazystream.Readable(() => fs.createReadStream('./test/resources/test.txt')), { // lazy stream 38 | name: 'test4.txt' 39 | }); 40 | archive.finalize(); 41 | 42 | let out = fs.createWriteStream('./target/test.zip'); 43 | archive.pipe(out); 44 | 45 | out.on('close', () => { 46 | cp.execFile('7z', ['e', `target${path.sep}test.zip`, '-otarget', '-p123'], (e) => { 47 | should.not.exist(e, '7z throws error: ' + e); 48 | fs.existsSync('./target/test.txt').should.be.true('Extracted file should exist'); 49 | fs.existsSync('./target/test2.txt').should.be.true('Extracted file should exist'); 50 | fs.existsSync('./target/test3.txt').should.be.true('Extracted file should exist'); 51 | 52 | const originalFileContents = fs.readFileSync('./test/resources/test.txt').toString('utf-8'); 53 | 54 | fs.readFileSync('./target/test.txt').toString('utf-8').should.be.eql( 55 | originalFileContents 56 | ); 57 | fs.readFileSync('./target/test2.txt').toString('utf-8').should.be.eql( 58 | originalFileContents 59 | ); 60 | 61 | done(); 62 | }); 63 | }); 64 | }); 65 | 66 | // setting compression to 0 to overcome bug (?) in 16.02 7z (only available version of 7z in travis) 67 | // modern 7z (and WinZip as well) on Windows 10 does unpack compressed encrypted empty files w/o issues 68 | it('should pack empty file with zip-aes and unpack with 7z', (done) => { 69 | let archive = archiver.create('zip-encrypted', {zlib: {level: 0}, encryptionMethod: 'aes256', password: '123'}); 70 | archive.append(fs.createReadStream('./test/resources/empty-file.txt'), { 71 | name: 'test.txt' 72 | }); 73 | archive.append(fs.createReadStream('./test/resources/test.txt'), { 74 | name: 'test2.txt' 75 | }); 76 | archive.finalize(); 77 | 78 | let out = fs.createWriteStream('./target/test.zip'); 79 | archive.pipe(out); 80 | 81 | out.on('close', () => { 82 | cp.execFile('7z', ['e', `target${path.sep}test.zip`, '-otarget', '-p123'], (e, stdout, stderr) => { 83 | should.not.exist(e, '7z throws error: ' + e + '.\nError output: ' + stderr); 84 | 85 | fs.existsSync('./target/test.txt').should.be.true('Extracted file should exist'); 86 | fs.existsSync('./target/test2.txt').should.be.true('Extracted file should exist'); 87 | 88 | fs.readFileSync('./target/test.txt').toString('utf-8').should.be.eql(''); 89 | fs.readFileSync('./target/test2.txt').toString('utf-8').should.be.eql( 90 | fs.readFileSync('./test/resources/test.txt').toString('utf-8')); 91 | 92 | done(); 93 | }); 94 | }); 95 | }); 96 | 97 | it('should pack directory with zip-aes and unpack with 7z', (done) => { 98 | let archive = archiver.create('zip-encrypted', {zlib: {level: 8}, encryptionMethod: 'aes256', password: '123'}); 99 | archive.directory('./test/resources/dir', 'dir'); 100 | archive.finalize(); 101 | 102 | let out = fs.createWriteStream('./target/test.zip'); 103 | archive.pipe(out); 104 | 105 | out.on('close', () => { 106 | cp.execFile('7z', ['e', `target${path.sep}test.zip`, '-spf', '-otarget', '-p123'], (e, stdout, stderr) => { 107 | should.not.exist(e, '7z throws error: ' + e + '.\nError output: ' + stderr); 108 | 109 | fs.existsSync('./target/dir/sub/test.txt').should.be.true('Extracted directory and file should exist'); 110 | 111 | const originalFileContents = fs.readFileSync('./test/resources/dir/sub/test.txt').toString('utf-8'); 112 | 113 | fs.readFileSync('./target/dir/sub/test.txt').toString('utf-8').should.be.eql( 114 | originalFileContents 115 | ); 116 | 117 | done(); 118 | }); 119 | }); 120 | }); 121 | }); -------------------------------------------------------------------------------- /test/zip-encrypted.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const ZipEncrypted = require('../lib/zip-encrypted'); 4 | const archiver = require('archiver'); 5 | const should = require('should'); 6 | 7 | describe('zip-encrypted', () => { 8 | before(() => { 9 | try { 10 | archiver.registerFormat('zip-encrypted', ZipEncrypted); 11 | } catch (e) { 12 | // already registered 13 | } 14 | }); 15 | 16 | it('should fail if password is not provided', () => { 17 | (() => archiver.create('zip-encrypted', {zlib: {level: 8}, encryptionMethod: 'zip20'})).should.throw(); 18 | }); 19 | 20 | it('should fail if encryption method is not provided', () => { 21 | (() => archiver.create('zip-encrypted', {zlib: {level: 8}, password: '123'})).should.throw(); 22 | }); 23 | 24 | it('should fail if nothing is not provided', () => { 25 | (() => archiver.create('zip-encrypted')).should.throw(); 26 | }); 27 | 28 | it('fallback construction', () => { 29 | should(ZipEncrypted({ encryptionMethod: 'zip20', password: '123'})).not.be.undefined(); 30 | }); 31 | }); -------------------------------------------------------------------------------- /test/zip20.js: -------------------------------------------------------------------------------- 1 | const archiver = require('archiver'); 2 | const fs = require('fs'); 3 | const cp = require('child_process'); 4 | const rmrf = require('rimraf'); 5 | const should = require('should'); 6 | const path = require('path'); 7 | 8 | /** 9 | * This test assumes 7-Zip installed in the system and available in path 10 | */ 11 | describe('zip-crypto', () => { 12 | before(() => { 13 | try { 14 | archiver.registerFormat('zip-encrypted', require('../lib/zip-encrypted')); 15 | } catch (e) { 16 | // already registered 17 | } 18 | }); 19 | 20 | beforeEach(() => { 21 | rmrf.sync('./target'); 22 | fs.mkdirSync('./target', {recursive: true}); 23 | }); 24 | 25 | it('should pack stream zip-crypto/unpack 7z', (done) => { 26 | let archive = archiver.create('zip-encrypted', {zlib: {level: 8}, encryptionMethod: 'zip20', password: Buffer.from('123')}); 27 | archive.append(fs.createReadStream('./test/resources/test.txt'), { 28 | name: 'test.txt' 29 | }); 30 | archive.finalize(); 31 | 32 | let out = fs.createWriteStream('./target/test.zip'); 33 | archive.pipe(out); 34 | 35 | out.on('close', () => { 36 | cp.execFile('7z', ['e', `target${path.sep}test.zip`, '-otarget', '-p123'], (e) => { 37 | should.not.exist(e, '7z throws error: ' + e); 38 | fs.existsSync('./target/test.txt').should.be.true('Extracted file should exist'); 39 | fs.readFileSync('./target/test.txt').toString('utf-8').should.be.eql( 40 | fs.readFileSync('./test/resources/test.txt').toString('utf-8') 41 | ); 42 | 43 | done(); 44 | }); 45 | }); 46 | }); 47 | 48 | it('should pack string zip-crypto/unpack 7z', (done) => { 49 | let archive = archiver.create('zip-encrypted', {zlib: {level: 8}, encryptionMethod: 'zip20', password: Buffer.from('123')}); 50 | archive.append('test data', { 51 | name: 'test.txt' 52 | }); 53 | archive.finalize(); 54 | 55 | let out = fs.createWriteStream('./target/test.zip'); 56 | archive.pipe(out); 57 | 58 | out.on('close', () => { 59 | cp.execFile('7z', ['e', `target${path.sep}test.zip`, '-otarget', '-p123'], (e) => { 60 | should.not.exist(e, '7z throws error: ' + e); 61 | fs.existsSync('./target/test.txt').should.be.true('Extracted file should exist'); 62 | fs.readFileSync('./target/test.txt').toString('utf-8').should.be.eql('test data'); 63 | 64 | done(); 65 | }); 66 | }); 67 | }); 68 | }); --------------------------------------------------------------------------------