neozipkit 0.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +400 -0
- package/contracts/Lock.sol +34 -0
- package/contracts/bytecode.txt +1 -0
- package/contracts/compile-contract.js +168 -0
- package/contracts/deploy/deploy-both-contracts.js +286 -0
- package/contracts/deploy/deploy-enhanced-contract.js +197 -0
- package/contracts/deploy/deploy-private-contract.js +190 -0
- package/contracts/deploy/deploy-public-clean.js +1063 -0
- package/contracts/deploy/deploy-public-contract.js +1107 -0
- package/contracts/deployment.config.example.js +25 -0
- package/contracts/remix-compile.js +222 -0
- package/contracts/setup-deployment.js +51 -0
- package/contracts/src/NZIP-NFT-Private.sol +350 -0
- package/contracts/src/NZIP-NFT.sol +265 -0
- package/contracts/src/ZipFileNFT-DEPRECATED-6field.sol +260 -0
- package/contracts/src/ZipFileNFT-DEPRECATED-Enhanced.sol +289 -0
- package/dist/browser/CertificateGeneratorBrowser.d.ts +75 -0
- package/dist/browser/CertificateGeneratorBrowser.js +433 -0
- package/dist/browser/TokenVerifierBrowser.d.ts +76 -0
- package/dist/browser/TokenVerifierBrowser.js +299 -0
- package/dist/browser/ZipKitBrowser.d.ts +18 -0
- package/dist/browser/ZipKitBrowser.js +250 -0
- package/dist/browser/ZipKitStampBrowser.d.ts +2 -0
- package/dist/browser/ZipKitStampBrowser.js +12 -0
- package/dist/browser-index.d.ts +21 -0
- package/dist/browser-index.js +58 -0
- package/dist/browser.d.ts +21 -0
- package/dist/browser.js +58 -0
- package/dist/index.d.ts +29 -0
- package/dist/index.js +76 -0
- package/dist/server/blockchain/CertificateToken.d.ts +48 -0
- package/dist/server/blockchain/CertificateToken.js +386 -0
- package/dist/server/blockchain/NFTMinter.d.ts +41 -0
- package/dist/server/blockchain/NFTMinter.js +323 -0
- package/dist/server/blockchain/TokenQuerier.d.ts +31 -0
- package/dist/server/blockchain/TokenQuerier.js +259 -0
- package/dist/server/blockchain/TokenVerifier.d.ts +20 -0
- package/dist/server/blockchain/TokenVerifier.js +395 -0
- package/dist/server/blockchain/WalletAnalyzer.d.ts +81 -0
- package/dist/server/blockchain/WalletAnalyzer.js +356 -0
- package/dist/server/blockchain/WalletFormatter.d.ts +39 -0
- package/dist/server/blockchain/WalletFormatter.js +196 -0
- package/dist/server/blockchain/WalletManager.d.ts +46 -0
- package/dist/server/blockchain/WalletManager.js +294 -0
- package/dist/server/blockchain/ZipMetadata.d.ts +27 -0
- package/dist/server/blockchain/ZipMetadata.js +131 -0
- package/dist/server/blockchain/ZipTokenProcessor.d.ts +44 -0
- package/dist/server/blockchain/ZipTokenProcessor.js +204 -0
- package/dist/server/blockchain/constants.d.ts +102 -0
- package/dist/server/blockchain/constants.js +968 -0
- package/dist/server/blockchain/index.d.ts +9 -0
- package/dist/server/blockchain/index.js +44 -0
- package/dist/server/blockchain/test-certificate.d.ts +8 -0
- package/dist/server/blockchain/test-certificate.js +100 -0
- package/dist/server/blockchain/types.d.ts +69 -0
- package/dist/server/blockchain/types.js +51 -0
- package/dist/server/platform/server/ZipKitServer.d.ts +105 -0
- package/dist/server/platform/server/ZipKitServer.js +437 -0
- package/dist/server/platform/servercomponents/ZipKitOTS.d.ts +91 -0
- package/dist/server/platform/servercomponents/ZipKitOTS.js +271 -0
- package/dist/shared/ZipEntry.d.ts +131 -0
- package/dist/shared/ZipEntry.js +686 -0
- package/dist/shared/ZipKit.d.ts +249 -0
- package/dist/shared/ZipKit.js +789 -0
- package/dist/shared/components/CertificateOTS.d.ts +15 -0
- package/dist/shared/components/CertificateOTS.js +116 -0
- package/dist/shared/components/FileSys.d.ts +2 -0
- package/dist/shared/components/FileSys.js +113 -0
- package/dist/shared/components/HashAccumulator.d.ts +55 -0
- package/dist/shared/components/HashAccumulator.js +100 -0
- package/dist/shared/components/Support.d.ts +63 -0
- package/dist/shared/components/Support.js +70 -0
- package/dist/shared/components/Util.d.ts +21 -0
- package/dist/shared/components/Util.js +115 -0
- package/dist/shared/components/ZipCrypto.d.ts +3 -0
- package/dist/shared/components/ZipCrypto.js +78 -0
- package/dist/shared/components/merkleTree.d.ts +66 -0
- package/dist/shared/components/merkleTree.js +136 -0
- package/dist/shared/constants/Errors.d.ts +53 -0
- package/dist/shared/constants/Errors.js +69 -0
- package/dist/shared/constants/Headers.d.ts +167 -0
- package/dist/shared/constants/Headers.js +191 -0
- package/dist/shared/types/index.d.ts +21 -0
- package/dist/shared/types/index.js +3 -0
- package/dist/shared/types.d.ts +33 -0
- package/dist/shared/types.js +8 -0
- package/dist/shared/version.d.ts +4 -0
- package/dist/shared/version.js +7 -0
- package/dist/types/index.d.ts +21 -0
- package/dist/types/index.js +3 -0
- package/examples/unzip-token.ts +488 -0
- package/examples/zip-token.ts +604 -0
- package/package.json +117 -0
- package/src/browser/CertificateGeneratorBrowser.ts +498 -0
- package/src/browser/TokenVerifierBrowser.ts +344 -0
- package/src/browser/ZipKitBrowser.ts +242 -0
- package/src/browser/ZipKitStampBrowser.ts +9 -0
- package/src/browser-index.ts +36 -0
- package/src/index.ts +48 -0
- package/src/server/blockchain/CertificateToken.ts +444 -0
- package/src/server/blockchain/NFTMinter.ts +357 -0
- package/src/server/blockchain/TokenQuerier.ts +287 -0
- package/src/server/blockchain/TokenVerifier.ts +453 -0
- package/src/server/blockchain/WalletAnalyzer.ts +397 -0
- package/src/server/blockchain/WalletFormatter.ts +206 -0
- package/src/server/blockchain/WalletManager.ts +294 -0
- package/src/server/blockchain/ZipMetadata.ts +117 -0
- package/src/server/blockchain/ZipTokenProcessor.ts +234 -0
- package/src/server/blockchain/constants.ts +969 -0
- package/src/server/blockchain/index.ts +42 -0
- package/src/server/blockchain/test-certificate.ts +137 -0
- package/src/server/blockchain/types.ts +134 -0
- package/src/server/platform/server/ZipKitServer.ts +459 -0
- package/src/server/platform/servercomponents/ZipKitOTS.ts +313 -0
- package/src/server/platform/servercomponents/opentimestamps.d.ts +23 -0
- package/src/shared/ZipEntry.ts +767 -0
- package/src/shared/ZipKit.ts +899 -0
- package/src/shared/components/CertificateOTS.ts +132 -0
- package/src/shared/components/FileSys.ts +87 -0
- package/src/shared/components/HashAccumulator.ts +113 -0
- package/src/shared/components/Support.ts +77 -0
- package/src/shared/components/Util.ts +113 -0
- package/src/shared/components/ZipCrypto.ts +91 -0
- package/src/shared/components/merkleTree.ts +162 -0
- package/src/shared/constants/Errors.ts +82 -0
- package/src/shared/constants/Headers.ts +203 -0
- package/src/shared/types/index.ts +25 -0
- package/src/shared/types/modules.d.ts +22 -0
- package/src/shared/types/opentimestamps.d.ts +23 -0
- package/src/shared/types.d.ts +8 -0
- package/src/shared/types.ts +43 -0
- package/src/shared/version.ts +4 -0
- package/src/types/index.ts +25 -0
- package/src/types/modules.d.ts +22 -0
- package/src/types/opentimestamps.d.ts +23 -0
|
@@ -0,0 +1,437 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* ZipKitServer
|
|
4
|
+
* Copyright (c) 2025 NeoWare, Inc. All rights reserved.
|
|
5
|
+
*
|
|
6
|
+
* Server-side implementation of ZipKit that passes through all functions
|
|
7
|
+
* directly to the parent ZipKit class. This class provides a consistent interface
|
|
8
|
+
* for server environments and ensures all ZipKit functionality is available.
|
|
9
|
+
*/
|
|
10
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
11
|
+
if (k2 === undefined) k2 = k;
|
|
12
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
13
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
14
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
15
|
+
}
|
|
16
|
+
Object.defineProperty(o, k2, desc);
|
|
17
|
+
}) : (function(o, m, k, k2) {
|
|
18
|
+
if (k2 === undefined) k2 = k;
|
|
19
|
+
o[k2] = m[k];
|
|
20
|
+
}));
|
|
21
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
22
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
23
|
+
}) : function(o, v) {
|
|
24
|
+
o["default"] = v;
|
|
25
|
+
});
|
|
26
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
27
|
+
var ownKeys = function(o) {
|
|
28
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
29
|
+
var ar = [];
|
|
30
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
31
|
+
return ar;
|
|
32
|
+
};
|
|
33
|
+
return ownKeys(o);
|
|
34
|
+
};
|
|
35
|
+
return function (mod) {
|
|
36
|
+
if (mod && mod.__esModule) return mod;
|
|
37
|
+
var result = {};
|
|
38
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
39
|
+
__setModuleDefault(result, mod);
|
|
40
|
+
return result;
|
|
41
|
+
};
|
|
42
|
+
})();
|
|
43
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
44
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
45
|
+
};
|
|
46
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
47
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
48
|
+
};
|
|
49
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
50
|
+
exports.Headers = void 0;
|
|
51
|
+
const fs = __importStar(require("fs"));
|
|
52
|
+
const path = __importStar(require("path"));
|
|
53
|
+
const uuid_1 = require("uuid");
|
|
54
|
+
const process_1 = require("process");
|
|
55
|
+
const ZipKit_1 = __importStar(require("../../../shared/ZipKit"));
|
|
56
|
+
const ZipKitOTS_1 = require("../servercomponents/ZipKitOTS");
|
|
57
|
+
const Headers = __importStar(require("../../../shared/constants/Headers"));
|
|
58
|
+
exports.Headers = Headers;
|
|
59
|
+
const Util_1 = require("../../../shared/components/Util");
|
|
60
|
+
const CertificateOTS_1 = __importDefault(require("../../../shared/components/CertificateOTS"));
|
|
61
|
+
const Errors_1 = __importDefault(require("../../../shared/constants/Errors"));
|
|
62
|
+
// Re-export everything from ZipKit
|
|
63
|
+
__exportStar(require("../../../shared/ZipKit"), exports);
|
|
64
|
+
/**
|
|
65
|
+
* This implementation is optimized for server environments and handles all
|
|
66
|
+
* ZIP operations including compression, extraction, encryption, and file management.
|
|
67
|
+
*/
|
|
68
|
+
class ZipKitServer extends ZipKit_1.default {
|
|
69
|
+
/**
|
|
70
|
+
* Creates a new ZipKitServer instance
|
|
71
|
+
*
|
|
72
|
+
* Initializes the parent ZipKit class and logs environment support information
|
|
73
|
+
* for diagnostic purposes.
|
|
74
|
+
*/
|
|
75
|
+
constructor() {
|
|
76
|
+
super(); // Call the parent constructor
|
|
77
|
+
// console.log('ZipKit.support.isNode: ', ZipKit.support.isNode);
|
|
78
|
+
// console.log('ZipKit.support.buffer: ', ZipKit.support.buffer);
|
|
79
|
+
// console.log('ZipKit.support.blob: ', ZipKit.support.blob);
|
|
80
|
+
// console.log('ZipKit.support.streams: ', ZipKit.support.streams);
|
|
81
|
+
// console.log('ZipKit.support.fileReader: ', ZipKit.support.fileReader);
|
|
82
|
+
}
|
|
83
|
+
/**
|
|
84
|
+
* Loads a ZIP file from the filesystem for updating/creating operations
|
|
85
|
+
*
|
|
86
|
+
* Attempts to read an existing ZIP file, but creates a new empty archive if
|
|
87
|
+
* the file doesn't exist. This method is used when adding or updating entries
|
|
88
|
+
* in an archive, handling both new and existing ZIP files gracefully.
|
|
89
|
+
*
|
|
90
|
+
* @param zipFile - Path to the ZIP file to load or create
|
|
91
|
+
*/
|
|
92
|
+
loadZipFile(zipFile) {
|
|
93
|
+
let inBuffer = null;
|
|
94
|
+
let fdIn = null;
|
|
95
|
+
try {
|
|
96
|
+
if (fs.existsSync(zipFile)) {
|
|
97
|
+
fdIn = fs.openSync(zipFile, 'r');
|
|
98
|
+
const stats = fs.fstatSync(fdIn);
|
|
99
|
+
inBuffer = Buffer.alloc(stats.size);
|
|
100
|
+
fs.readSync(fdIn, inBuffer, 0, stats.size, 0);
|
|
101
|
+
}
|
|
102
|
+
else {
|
|
103
|
+
// File doesn't exist, use an empty buffer
|
|
104
|
+
inBuffer = Buffer.alloc(0);
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
catch (error) {
|
|
108
|
+
console.log('Warning: Could not open existing file. Creating new archive.');
|
|
109
|
+
inBuffer = Buffer.alloc(0);
|
|
110
|
+
}
|
|
111
|
+
finally {
|
|
112
|
+
if (fdIn !== null) {
|
|
113
|
+
fs.closeSync(fdIn);
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
// Initialize empty buffer if null
|
|
117
|
+
const buffer = inBuffer || Buffer.alloc(0);
|
|
118
|
+
super.loadZip(buffer);
|
|
119
|
+
}
|
|
120
|
+
/**
|
|
121
|
+
* Loads a ZIP file from the filesystem for extraction and listing operations
|
|
122
|
+
*
|
|
123
|
+
* Reads an existing ZIP file and throws an error if the file doesn't exist.
|
|
124
|
+
* Use this method when working with existing archives that need to be extracted.
|
|
125
|
+
*
|
|
126
|
+
* @param zipFile - Path to the ZIP file to load
|
|
127
|
+
* @throws Error if the file doesn't exist or can't be read
|
|
128
|
+
*/
|
|
129
|
+
loadUnzipFile(zipFile) {
|
|
130
|
+
try {
|
|
131
|
+
// Check if the file exists before trying to read it
|
|
132
|
+
if (!fs.existsSync(zipFile)) {
|
|
133
|
+
console.error(`Error: Zip file "${zipFile}" does not exist`);
|
|
134
|
+
(0, process_1.exit)(1);
|
|
135
|
+
}
|
|
136
|
+
const inBuffer = fs.readFileSync(zipFile);
|
|
137
|
+
super.loadZip(inBuffer);
|
|
138
|
+
}
|
|
139
|
+
catch (error) {
|
|
140
|
+
console.error(`Error: Failed to read zip file "${zipFile}"`);
|
|
141
|
+
(0, process_1.exit)(1);
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
/**
|
|
145
|
+
* Adds a single file to the ZIP archive
|
|
146
|
+
* @param filename - Path to the file to be added
|
|
147
|
+
* @param comment - Optional comment for the file entry
|
|
148
|
+
*
|
|
149
|
+
* Handles:
|
|
150
|
+
* - Creating/updating ZipEntry objects
|
|
151
|
+
* - Setting file attributes and timestamps
|
|
152
|
+
* - Respecting freshen (-f) and update (-u) flags
|
|
153
|
+
* - Setting compression method
|
|
154
|
+
*/
|
|
155
|
+
addFile(filename, freshen = false, update = false) {
|
|
156
|
+
let entry = super.getZipEntry(filename);
|
|
157
|
+
if (!entry) {
|
|
158
|
+
// Check for Freshen option
|
|
159
|
+
if (freshen)
|
|
160
|
+
return;
|
|
161
|
+
entry = super.createZipEntry(filename);
|
|
162
|
+
}
|
|
163
|
+
else if (!update) {
|
|
164
|
+
// Mark this entry as not being updated
|
|
165
|
+
entry.isUpdated = false;
|
|
166
|
+
return;
|
|
167
|
+
}
|
|
168
|
+
entry.platform = process.platform;
|
|
169
|
+
// Correctly retrieve file stats
|
|
170
|
+
let attr = fs.statSync(filename); // Synchronously get the stats of the file
|
|
171
|
+
entry.uncompressedSize = attr.size;
|
|
172
|
+
// Set the DOS file time/date based on the Date stamp of the file.
|
|
173
|
+
const utcDate = new Date(attr.mtime.getTime());
|
|
174
|
+
entry.timeDateDOS = entry.setDateTime(utcDate);
|
|
175
|
+
entry.universalTime = Math.floor(attr.mtime.getTime() / 1000); // Store Unix timestamp
|
|
176
|
+
// Set Unix UID/GID if on Unix-like system
|
|
177
|
+
if (process.platform !== 'win32') {
|
|
178
|
+
entry.uid = attr.uid;
|
|
179
|
+
entry.gid = attr.gid;
|
|
180
|
+
}
|
|
181
|
+
// Use attr.mode for file permissions
|
|
182
|
+
entry.isDirectory = attr.isDirectory();
|
|
183
|
+
let _fattr = (attr.mode & 0xfff) | (entry.isDirectory ? 0x4000 : 0x8000);
|
|
184
|
+
entry.extFileAttr = ((_fattr << 16) | (entry.isDirectory ? 0x10 : 0)) >>> 0;
|
|
185
|
+
// Set Compression method
|
|
186
|
+
// if (options.store) {
|
|
187
|
+
// entry.cmpMethod = CMP_METHOD.STORED;
|
|
188
|
+
// } else if (options.Z) {
|
|
189
|
+
// entry.cmpMethod = Headers.CMP_METHOD.DEFLATED;
|
|
190
|
+
// } else {
|
|
191
|
+
// entry.cmpMethod = CMP_METHOD.ZSTD;
|
|
192
|
+
// }
|
|
193
|
+
}
|
|
194
|
+
/**
|
|
195
|
+
* Processes files to be added to the ZIP archive
|
|
196
|
+
* Creates ZipEntry objects for each file and initiates the compression process
|
|
197
|
+
*/
|
|
198
|
+
addFiles(files, freshen = false, update = false) {
|
|
199
|
+
let filesAdded = 0;
|
|
200
|
+
for (var i = 0; files[i] != undefined; i++) {
|
|
201
|
+
const filename = String(files[i]);
|
|
202
|
+
// console.log('filename: ', filename);
|
|
203
|
+
// Skip arguments that look like options (start with hyphen but aren't files)
|
|
204
|
+
if (filename.startsWith('-') && !fs.existsSync(filename)) {
|
|
205
|
+
console.warn(`Warning: Skipping '${filename}' which appears to be an option, not a file.`);
|
|
206
|
+
continue;
|
|
207
|
+
}
|
|
208
|
+
this.addFile(filename, freshen, update);
|
|
209
|
+
filesAdded++;
|
|
210
|
+
}
|
|
211
|
+
return filesAdded;
|
|
212
|
+
}
|
|
213
|
+
/**
|
|
214
|
+
* Creates a ZIP file with optional OpenTimestamps (OTS) metadata
|
|
215
|
+
*
|
|
216
|
+
* This method creates a ZIP file with optional OpenTimestamps (OTS) metadata,
|
|
217
|
+
* which includes a timestamp of the ZIP file's contents on the Bitcoin blockchain.
|
|
218
|
+
*
|
|
219
|
+
* @param zipFile - The path to the ZIP file to create
|
|
220
|
+
* @param compressOptions - The compression options for the ZIP file
|
|
221
|
+
* @returns void - The method triggers a download of the ZIP file
|
|
222
|
+
*/
|
|
223
|
+
async createZip(zipFile, compressOptions) {
|
|
224
|
+
// Ensure the directory structure for the output file exists
|
|
225
|
+
const outputDir = path.dirname(zipFile);
|
|
226
|
+
if (!fs.existsSync(outputDir)) {
|
|
227
|
+
fs.mkdirSync(outputDir, { recursive: true });
|
|
228
|
+
}
|
|
229
|
+
// Generate a unique temporary file name in the output directory
|
|
230
|
+
const _tempZipFile = path.join(outputDir, `neozip-${(0, uuid_1.v4)()}.zip`);
|
|
231
|
+
// Open or create the .zip file for writing
|
|
232
|
+
const fd = fs.openSync(_tempZipFile, 'w');
|
|
233
|
+
let offset = await super.createZipFileData(compressOptions, {
|
|
234
|
+
onReadEntryData: (entry) => {
|
|
235
|
+
// console.log(`Reading file: ${entry.filename}`);
|
|
236
|
+
try {
|
|
237
|
+
return fs.readFileSync(entry.filename);
|
|
238
|
+
}
|
|
239
|
+
catch (error) {
|
|
240
|
+
throw new Error(`Failed to read file: ${entry.filename}`);
|
|
241
|
+
}
|
|
242
|
+
// return fs.readFileSync(entry.filename);
|
|
243
|
+
},
|
|
244
|
+
onOutputBuffer: (buffer) => {
|
|
245
|
+
fs.writeSync(fd, buffer);
|
|
246
|
+
},
|
|
247
|
+
onEntryDone: (entry, status) => {
|
|
248
|
+
console.log(`${status} ${entry.filename} to ${zipFile}`);
|
|
249
|
+
}
|
|
250
|
+
});
|
|
251
|
+
// Write the metadata entry to the .zip fi
|
|
252
|
+
await super.finishZipFileData(offset, function onOutputBuffer(buffer) {
|
|
253
|
+
fs.writeSync(fd, buffer);
|
|
254
|
+
}, undefined);
|
|
255
|
+
// Close the .zip file
|
|
256
|
+
fs.closeSync(fd);
|
|
257
|
+
// Delete the existing .zip file if it exists
|
|
258
|
+
if (fs.existsSync(zipFile)) {
|
|
259
|
+
fs.unlinkSync(zipFile);
|
|
260
|
+
}
|
|
261
|
+
// Replace the existing .zip file with the temporary file
|
|
262
|
+
fs.renameSync(_tempZipFile, zipFile);
|
|
263
|
+
}
|
|
264
|
+
/**
|
|
265
|
+
* Creates a ZIP file with OpenTimestamps (OTS) metadata
|
|
266
|
+
*
|
|
267
|
+
* This method creates a ZIP file with OpenTimestamps (OTS) metadata, which
|
|
268
|
+
* includes a timestamp of the ZIP file's contents on the Bitcoin blockchain.
|
|
269
|
+
*
|
|
270
|
+
* @param zipFile - The path to the ZIP file to create
|
|
271
|
+
* @param compressOptions - The compression options for the ZIP file
|
|
272
|
+
* @returns void - The method triggers a download of the ZIP file
|
|
273
|
+
*/
|
|
274
|
+
async createZipOTS(zipFile, compressOptions) {
|
|
275
|
+
// Ensure the directory structure for the output file exists
|
|
276
|
+
const outputDir = path.dirname(zipFile);
|
|
277
|
+
if (!fs.existsSync(outputDir)) {
|
|
278
|
+
fs.mkdirSync(outputDir, { recursive: true });
|
|
279
|
+
}
|
|
280
|
+
// Generate a unique temporary file name in the output directory
|
|
281
|
+
const _tempZipFile = path.join(outputDir, `neozip-${(0, uuid_1.v4)()}.zip`);
|
|
282
|
+
// Open or create the .zip file for writing
|
|
283
|
+
const fd = fs.openSync(_tempZipFile, 'w');
|
|
284
|
+
let offset = await super.createZipFileData(compressOptions, {
|
|
285
|
+
onReadEntryData: (entry) => {
|
|
286
|
+
// console.log(`Reading file: ${entry.filename}`);
|
|
287
|
+
try {
|
|
288
|
+
return fs.readFileSync(entry.filename);
|
|
289
|
+
}
|
|
290
|
+
catch (error) {
|
|
291
|
+
throw new Error(`Failed to read file: ${entry.filename}`);
|
|
292
|
+
}
|
|
293
|
+
// return fs.readFileSync(entry.filename);
|
|
294
|
+
},
|
|
295
|
+
onOutputBuffer: (buffer) => {
|
|
296
|
+
fs.writeSync(fd, buffer);
|
|
297
|
+
},
|
|
298
|
+
onEntryDone: (entry, status) => {
|
|
299
|
+
console.log(`${status} ${entry.filename} to ${zipFile}`);
|
|
300
|
+
}
|
|
301
|
+
});
|
|
302
|
+
// Timestamp the zip file to the Bitcoin blockchain
|
|
303
|
+
let _metadataEntry = null;
|
|
304
|
+
console.log('Timestamping to Bitcoin blockchain...');
|
|
305
|
+
const _merkleRoot = super.getMerkleRoot();
|
|
306
|
+
console.log('Merkle Root: ' + _merkleRoot);
|
|
307
|
+
const _ots = await (0, ZipKitOTS_1.createTimestamp)(_merkleRoot);
|
|
308
|
+
_metadataEntry = super.createTimestampMetadataEntry(_ots);
|
|
309
|
+
// Write the metadata entry to the .zip fi
|
|
310
|
+
await super.finishZipFileData(offset, function onOutputBuffer(buffer) {
|
|
311
|
+
fs.writeSync(fd, buffer);
|
|
312
|
+
}, _metadataEntry || undefined);
|
|
313
|
+
// Close the .zip file
|
|
314
|
+
fs.closeSync(fd);
|
|
315
|
+
// Delete the existing .zip file if it exists
|
|
316
|
+
if (fs.existsSync(zipFile)) {
|
|
317
|
+
fs.unlinkSync(zipFile);
|
|
318
|
+
}
|
|
319
|
+
// Replace the existing .zip file with the temporary file
|
|
320
|
+
fs.renameSync(_tempZipFile, zipFile);
|
|
321
|
+
}
|
|
322
|
+
/**
|
|
323
|
+
* Removes specified files from the ZIP archive
|
|
324
|
+
* Deletes matching ZipEntry objects and rebuilds the archive if any files were removed
|
|
325
|
+
*/
|
|
326
|
+
deleteFiles(delFiles) {
|
|
327
|
+
super.getDirectory();
|
|
328
|
+
let filesDel = 0;
|
|
329
|
+
delFiles.forEach(fname => {
|
|
330
|
+
const deleted = super.deleteFile(fname);
|
|
331
|
+
if (deleted) {
|
|
332
|
+
console.log(' deleting: ' + fname + "\n");
|
|
333
|
+
++filesDel;
|
|
334
|
+
}
|
|
335
|
+
else {
|
|
336
|
+
console.log(' warning: name not found: ' + fname + "\n");
|
|
337
|
+
}
|
|
338
|
+
});
|
|
339
|
+
return filesDel;
|
|
340
|
+
}
|
|
341
|
+
/**
|
|
342
|
+
* Upgrades a timestamp in an existing ZIP file
|
|
343
|
+
*
|
|
344
|
+
* This method takes an existing ZIP file and upgrades its timestamp by:
|
|
345
|
+
* 1. Loading the original ZIP file
|
|
346
|
+
* 2. Removing any existing timestamp metadata entries
|
|
347
|
+
* 3. Adding a new timestamp metadata entry with the upgraded OTS proof
|
|
348
|
+
* 4. Creating a new ZIP file with the updated timestamp
|
|
349
|
+
*
|
|
350
|
+
* @param zipFile - The original ZIP file to upgrade
|
|
351
|
+
* @param upgradedOts - The upgraded OpenTimestamps proof as an ArrayBuffer
|
|
352
|
+
* @returns void - The method triggers a download of the upgraded ZIP file
|
|
353
|
+
*/
|
|
354
|
+
async upgradeOTS(fileName, upgradedOts) {
|
|
355
|
+
// Generate a unique temporary file name in the output directory
|
|
356
|
+
let tempName = fileName.replace('.zip', '.upgrade.zip');
|
|
357
|
+
// Open or create the .zip file for writing
|
|
358
|
+
const fd = fs.openSync(tempName, 'w');
|
|
359
|
+
try {
|
|
360
|
+
const zipEntries = this.getDirectory();
|
|
361
|
+
let offset = 0;
|
|
362
|
+
// Copy the entries from the original file to the output file
|
|
363
|
+
for (const entry of zipEntries) {
|
|
364
|
+
if (entry.filename === ZipKit_1.TIMESTAMP_METADATA || entry.filename === ZipKit_1.TIMESTAMP_SUBMITTED) {
|
|
365
|
+
this.deleteFile(entry.filename);
|
|
366
|
+
}
|
|
367
|
+
else {
|
|
368
|
+
// Copy the entry data to the output file
|
|
369
|
+
console.log('Copying entry: ', entry.filename);
|
|
370
|
+
const inData = this.copyEntry(entry);
|
|
371
|
+
entry.localHdrOffset = offset;
|
|
372
|
+
offset += inData.length;
|
|
373
|
+
fs.writeSync(fd, inData);
|
|
374
|
+
}
|
|
375
|
+
}
|
|
376
|
+
// Add the new timestamp metadata file
|
|
377
|
+
let tsEntry = this.createZipEntry(ZipKit_1.TIMESTAMP_METADATA);
|
|
378
|
+
tsEntry.timeDateDOS = tsEntry.setDateTime(new Date());
|
|
379
|
+
tsEntry.compressedSize = upgradedOts.byteLength;
|
|
380
|
+
tsEntry.uncompressedSize = upgradedOts.byteLength;
|
|
381
|
+
tsEntry.cmpMethod = ZipKit_1.CMP_METHOD.STORED;
|
|
382
|
+
tsEntry.crc = (0, Util_1.crc32)(upgradedOts);
|
|
383
|
+
tsEntry.fileBuffer = upgradedOts;
|
|
384
|
+
console.log('tsEntry: ', tsEntry);
|
|
385
|
+
const localHdr = tsEntry.createLocalHdr();
|
|
386
|
+
// Save local header offset for entry and calculate next offset
|
|
387
|
+
tsEntry.localHdrOffset = offset;
|
|
388
|
+
offset += localHdr.length + tsEntry.compressedSize;
|
|
389
|
+
fs.writeSync(fd, localHdr);
|
|
390
|
+
fs.writeSync(fd, upgradedOts);
|
|
391
|
+
// Output ZipEntries as Central End Directory
|
|
392
|
+
const centralDirOffset = offset;
|
|
393
|
+
for (const entry of zipEntries) {
|
|
394
|
+
const centralDirEntry = entry.centralDirEntry();
|
|
395
|
+
offset += centralDirEntry.length;
|
|
396
|
+
fs.writeSync(fd, centralDirEntry);
|
|
397
|
+
}
|
|
398
|
+
const centralDirSize = offset - centralDirOffset;
|
|
399
|
+
let ceBuf = this.centralEndHdr(centralDirSize, centralDirOffset);
|
|
400
|
+
fs.writeSync(fd, ceBuf);
|
|
401
|
+
// Close the .zip file
|
|
402
|
+
fs.closeSync(fd);
|
|
403
|
+
// Delete the existing .zip file if it exists
|
|
404
|
+
if (fs.existsSync(fileName)) {
|
|
405
|
+
fs.unlinkSync(fileName);
|
|
406
|
+
}
|
|
407
|
+
// Replace the existing .zip file with the temporary file
|
|
408
|
+
fs.renameSync(tempName, fileName);
|
|
409
|
+
}
|
|
410
|
+
catch (err) {
|
|
411
|
+
console.error('Error-upgradeOTS: ', err);
|
|
412
|
+
}
|
|
413
|
+
}
|
|
414
|
+
async createCertificateOTS(fileName, zipEntries, timestampResult) {
|
|
415
|
+
if (!timestampResult || !timestampResult.merkleRoot || !fileName)
|
|
416
|
+
return Errors_1.default.CERTIFICATE_OTS_BAD;
|
|
417
|
+
let rsp = await (0, ZipKitOTS_1.deserializeOts)(timestampResult);
|
|
418
|
+
if (!rsp)
|
|
419
|
+
return Errors_1.default.CERTIFICATE_OTS_FAILED;
|
|
420
|
+
const result = JSON.parse(rsp);
|
|
421
|
+
const cert = (0, CertificateOTS_1.default)(result.attestStr, fileName, timestampResult.merkleRoot, result.needsUpdateMsg, result.attestationValues, zipEntries, false);
|
|
422
|
+
if (!cert)
|
|
423
|
+
return Errors_1.default.CERTIFICATE_OTS_FAILED;
|
|
424
|
+
// Generate certificate file name
|
|
425
|
+
const certFileName = fileName + '.certificate.html';
|
|
426
|
+
try {
|
|
427
|
+
// Write the certificate HTML to a file
|
|
428
|
+
fs.writeFileSync(certFileName, cert, { encoding: 'utf8' });
|
|
429
|
+
return `Certificate created as ${certFileName}`;
|
|
430
|
+
}
|
|
431
|
+
catch (error) {
|
|
432
|
+
console.error(`Failed to write certificate file: ${error}`);
|
|
433
|
+
return Errors_1.default.CERTIFICATE_OTS_FAILED;
|
|
434
|
+
}
|
|
435
|
+
}
|
|
436
|
+
}
|
|
437
|
+
exports.default = ZipKitServer;
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
declare global {
|
|
2
|
+
var _bitcore: any;
|
|
3
|
+
}
|
|
4
|
+
/**
|
|
5
|
+
* ZipKitOTS - OpenTimestamps utilities for NeoZip
|
|
6
|
+
*
|
|
7
|
+
* This module provides functions for creating and verifying OpenTimestamps
|
|
8
|
+
* proofs for ZIP archives and their contents. It includes utilities for timestamp
|
|
9
|
+
* creation, verification, and serialization/deserialization.
|
|
10
|
+
*/
|
|
11
|
+
/**
|
|
12
|
+
* Interface for timestamp verification results
|
|
13
|
+
* Contains all necessary information about a verified timestamp
|
|
14
|
+
*/
|
|
15
|
+
export interface TimestampResult {
|
|
16
|
+
merkleRoot: string | null;
|
|
17
|
+
ots: ArrayBuffer | null;
|
|
18
|
+
verified: boolean;
|
|
19
|
+
results: any | null;
|
|
20
|
+
error: string | null;
|
|
21
|
+
attestations: any | null;
|
|
22
|
+
upgradedOts: ArrayBuffer | null;
|
|
23
|
+
}
|
|
24
|
+
export interface TimestampInfo {
|
|
25
|
+
message: string;
|
|
26
|
+
results: string[];
|
|
27
|
+
attestDate: Date | null;
|
|
28
|
+
attestHeight: number | null;
|
|
29
|
+
submittedUri: string | null;
|
|
30
|
+
otsUpgraded: boolean;
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Verifies a timestamp proof against a file hash
|
|
34
|
+
*
|
|
35
|
+
* @param hashDigest - SHA-256 hash digest of the file or merkle root (hex string)
|
|
36
|
+
* @param otsData - The OpenTimestamps proof data
|
|
37
|
+
* @returns Promise with verification result or null on critical failure
|
|
38
|
+
*
|
|
39
|
+
* @example
|
|
40
|
+
* // Verify a timestamp proof
|
|
41
|
+
* const hashDigest = "8a9d..."; // SHA-256 digest in hex format
|
|
42
|
+
* const result = await verifyTimestamp(hashDigest, otsBuffer);
|
|
43
|
+
*
|
|
44
|
+
* if (result) {
|
|
45
|
+
* if (result.error) {
|
|
46
|
+
* console.error("Verification failed:", result.error);
|
|
47
|
+
* } else {
|
|
48
|
+
* console.log("Verification succeeded:", result.verified);
|
|
49
|
+
*
|
|
50
|
+
* if (result.upgradedOts) {
|
|
51
|
+
* // Save the upgraded timestamp
|
|
52
|
+
* }
|
|
53
|
+
* }
|
|
54
|
+
* }
|
|
55
|
+
*/
|
|
56
|
+
export declare function verifyTimestamp(hashDigest: string | null, ots: ArrayBuffer | null): Promise<TimestampResult | {
|
|
57
|
+
error: string;
|
|
58
|
+
} | null>;
|
|
59
|
+
/**
|
|
60
|
+
* Creates a timestamp proof for a file hash using OpenTimestamps
|
|
61
|
+
*
|
|
62
|
+
* @param hashDigest - SHA-256 hash digest of the file or merkle root (hex string)
|
|
63
|
+
* @returns Promise containing the OpenTimestamps proof or null on failure
|
|
64
|
+
*
|
|
65
|
+
* @example
|
|
66
|
+
* // Create a timestamp for a file hash
|
|
67
|
+
* const hashDigest = "8a9d..."; // SHA-256 digest in hex format
|
|
68
|
+
* const timestampProof = await createTimestamp(hashDigest);
|
|
69
|
+
*
|
|
70
|
+
* if (timestampProof) {
|
|
71
|
+
* // Save the timestamp proof to storage
|
|
72
|
+
* }
|
|
73
|
+
*/
|
|
74
|
+
export declare function createTimestamp(hashDigest: string | null): Promise<Buffer | null>;
|
|
75
|
+
/**
|
|
76
|
+
* Result of deserializing an OpenTimestamps proof
|
|
77
|
+
*/
|
|
78
|
+
export interface DeserializeOtsResult {
|
|
79
|
+
attestStr: string | null;
|
|
80
|
+
needsUpdateMsg: string | null;
|
|
81
|
+
attestationValues: any[];
|
|
82
|
+
}
|
|
83
|
+
/**
|
|
84
|
+
* Deserializes timestamp metadata to extract attestation information
|
|
85
|
+
* Used for generating timestamp certificates and displaying verification details
|
|
86
|
+
*
|
|
87
|
+
* @param tsResult - Timestamp verification result to deserialize
|
|
88
|
+
* @returns JSON string of deserialized data or null on failure
|
|
89
|
+
*/
|
|
90
|
+
export declare function deserializeOts(tsResult: TimestampResult): Promise<string | null>;
|
|
91
|
+
export declare function parseVerifyResult(verifyResult: TimestampResult): Promise<TimestampInfo>;
|