|
const fs = require("fs"); |
|
const crypto = require('crypto'); |
|
//const bitwise = require("bitwise"); |
|
|
|
const privateKey = fs.readFileSync("./private.pem"); |
|
|
|
// http://www.zlib.org/rfc-gzip.html |
|
// http://www.onicos.com/staff/iz/formats/gzip.html |
|
// https://de.wikipedia.org/wiki/Gzip |
|
|
|
// https://dev.to/somedood/bitmasks-a-very-esoteric-and-impractical-way-of-managing-booleans-1hlf |
|
// https://www.npmjs.com/package/bitwise |
|
// https://stackoverflow.com/questions/1436438/how-do-you-set-clear-and-toggle-a-single-bit-in-javascript |
|
|
|
|
|
function createSubHeader(key, payload) { |
|
|
|
// get charcode from key |
|
let s1 = key.charCodeAt(0); |
|
let s2 = key.charCodeAt(1); |
|
|
|
// calculate length bytes |
|
let l2 = Math.floor(payload.length / 256); |
|
let l1 = payload.length - (l2 * 256); |
|
|
|
/* |
|
let arr = []; |
|
|
|
for (let i = 0; i < payload.length; i++) { |
|
arr.push(payload.charCodeAt(i)); |
|
} |
|
*/ |
|
|
|
console.log("Len compar: %d - %d", payload.length, l2 * 256 + l1) |
|
|
|
|
|
return Buffer.concat([ |
|
Buffer.from([s1, s2, l1, l2]), |
|
Buffer.from(payload) |
|
]); |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
fs.readFile("./test-plugin.tgz", (err, bytes) => { |
|
|
|
if (err) { |
|
console.log(err); |
|
process.exit(100); |
|
} |
|
|
|
/* |
|
console.log("File length, bytes: %d", bytes.length); |
|
console.log(); |
|
|
|
|
|
// bitwise operation on header flags |
|
const FLAG_RESERVED_3 = (bytes[3] >> 7) & 1; |
|
const FLAG_RESERVED_2 = (bytes[3] >> 6) & 1; |
|
const FLAG_RESERVED_1 = (bytes[3] >> 5) & 1; |
|
const FLAG_COMMENT = (bytes[3] >> 4) & 1; |
|
const FLAG_NAME = (bytes[3] >> 3) & 1; |
|
const FLAG_EXTRA = (bytes[3] >> 2) & 1; |
|
const FLAG_CRC = (bytes[3] >> 1) & 1; |
|
const FLAG_TEXT = (bytes[3] >> 0) & 1; |
|
|
|
console.log("FLAG_RESERVED_3", FLAG_RESERVED_3); |
|
console.log("FLAG_RESERVED_2", FLAG_RESERVED_2); |
|
console.log("FLAG_RESERVED_1", FLAG_RESERVED_1); |
|
console.log("FLAG_COMMENT", FLAG_COMMENT); |
|
console.log("FLAG_NAME", FLAG_NAME); |
|
console.log("FLAG_EXTRA", FLAG_EXTRA); |
|
console.log("FLAG_CRC", FLAG_CRC); |
|
console.log("FLAG_TEXT", FLAG_TEXT); |
|
console.log(); |
|
|
|
let HEADER_EXTRA_LENGTH = 0; |
|
let HEADER_EXTRA_OBJECT = {}; |
|
|
|
let HEADER_NAME_LENGTH = 0; |
|
let HEADER_NAME = ""; |
|
|
|
let HEADER_COMMENT_LENGTH = 0; |
|
let HEADER_COMMENT = ""; |
|
round |
|
|
|
let BODY_START_BYTE = 10; // = header length |
|
let BODY_END_BYTE = bytes.length - 8; |
|
|
|
|
|
|
|
if (FLAG_EXTRA) { |
|
|
|
let offset = 0; |
|
let len1 = bytes[10]; |
|
let len2 = bytes[11]; |
|
HEADER_EXTRA_LENGTH = len1 + (len2 * 256); |
|
BODY_START_BYTE += HEADER_EXTRA_LENGTH + 2; |
|
|
|
|
|
console.log("Extra header length", HEADER_EXTRA_LENGTH); |
|
let extra = bytes.slice(12, 12 + HEADER_EXTRA_LENGTH); |
|
|
|
|
|
while (HEADER_EXTRA_LENGTH > offset) { |
|
|
|
let s1 = extra[offset + 0]; |
|
let s2 = extra[offset + 1]; |
|
let l1 = extra[offset + 2]; |
|
let l2 = extra[offset + 3]; |
|
|
|
let length = l1 + (l2 * 256); |
|
let end = offset + 4 + length; |
|
|
|
// read & store sub-header in object |
|
HEADER_EXTRA_OBJECT[`${String.fromCharCode(s1)}${String.fromCharCode(s2)}`] = extra.slice(offset + 4, end).toString(); |
|
|
|
// set offset |
|
offset = end; |
|
|
|
} |
|
|
|
console.log(HEADER_EXTRA_OBJECT); |
|
|
|
} |
|
|
|
|
|
if (FLAG_NAME) { |
|
|
|
let start = 10; |
|
let offset = 0; |
|
let counter = 0; |
|
|
|
// add extra header length to offset |
|
// + 2 for length bytes for extra header |
|
offset += HEADER_EXTRA_LENGTH; |
|
|
|
|
|
|
|
if (FLAG_EXTRA) { |
|
// + 2 for length bytes |
|
offset += 2; |
|
} |
|
|
|
|
|
|
|
// read til we reach the "zero" terminating |
|
while (bytes[start + offset + counter] !== 0) { |
|
HEADER_NAME += String.fromCharCode(bytes[start + offset + counter]); |
|
counter += 1; |
|
} |
|
|
|
HEADER_NAME_LENGTH = counter; |
|
BODY_START_BYTE += counter + 1; // +1 for zero terminating |
|
|
|
console.log("Original name: '%s'", HEADER_NAME); |
|
|
|
} |
|
|
|
|
|
if (FLAG_COMMENT) { |
|
|
|
let start = 10; |
|
let offset = 0; |
|
let counter = 0; |
|
|
|
// add offset |
|
offset += HEADER_EXTRA_LENGTH; |
|
offset += HEADER_NAME_LENGTH; |
|
|
|
if (FLAG_EXTRA) { |
|
// for length bytes |
|
offset += 2; |
|
} |
|
|
|
|
|
if (FLAG_NAME) { |
|
// + 1 for zero terminating |
|
// original name field |
|
offset += 1; |
|
} |
|
|
|
|
|
// read til we reach the "zero" terminating |
|
while (bytes[start + offset + counter] !== 0) { |
|
HEADER_COMMENT += String.fromCharCode(bytes[start + offset + counter]); |
|
counter += 1; |
|
} |
|
|
|
HEADER_COMMENT_LENGTH = counter; |
|
BODY_START_BYTE += counter + 1; // +1 for zero terminating |
|
|
|
console.log("Comment: '%s'", HEADER_COMMENT); |
|
|
|
} |
|
|
|
|
|
if (FLAG_CRC) { |
|
HEADER_CRC_LENGTH = 2; |
|
BODY_START_BYTE += 2; |
|
} |
|
*/ |
|
|
|
|
|
|
|
let body = bytes.slice(10, bytes.length - 8); |
|
|
|
|
|
console.log("Body length:", body.length); |
|
console.log(Buffer.from(body).toString("base64")); |
|
console.log(); |
|
|
|
|
|
var signer = crypto.createSign('sha256'); |
|
signer.update(body); // -> this is the tar body |
|
var sign = signer.sign(privateKey, 'base64'); |
|
|
|
console.log("SIGN:", sign); |
|
console.log(); |
|
|
|
|
|
|
|
|
|
|
|
let payload = Buffer.concat([ |
|
createSubHeader("vs", sign), |
|
//createSubHeader("vd", "abcdefghijklmnopäääääääääääääääääääääääääääääääääääääääääääääääääääääääääääääääääääääääääääääääääääääääääääääääääääääääääääääääääääääääää"), // ERROR |
|
// createSubHeader("vd", "="), // OK |
|
createSubHeader("ai", "eyJuYW1lIjoiTWFyYyBTdGlybmVyIiwiZW1haWwiOiJtYXJjLnN0aXJuZXJAb3Blbi1oYXVzLmlvIn0=") |
|
]); |
|
|
|
|
|
// calculate length bytes |
|
let toround = payload.length / 256; |
|
let l2 = Math.floor(toround); |
|
let l1 = payload.length - (l2 * 256); |
|
|
|
|
|
console.log("to round", toround); |
|
console.log("len1: %d len2: %d, payload: %d", l1, l2, payload.length) |
|
|
|
|
|
let EXTRA_HEADER = Buffer.concat([ |
|
Buffer.from([l1, l2]), |
|
payload |
|
]); |
|
|
|
|
|
//console.log(EXTRA_HEADER.length - 2) |
|
|
|
|
|
|
|
// set extra header bits |
|
//bytes[3] &= ~(1 << 0); // FTEXT |
|
//bytes[3] &= ~(1 << 1); // FHCRC |
|
bytes[3] |= (1 << 2); // FEXTRA |
|
//bytes[3] &= ~(1 << 3); // FNAME |
|
//bytes[3] &= ~(1 << 4); // FCOMMENT |
|
//bytes[3] &= ~(1 << 5); // reserved |
|
//bytes[3] &= ~(1 << 6); // reserved |
|
//bytes[3] &= ~(1 << 7); // reserved |
|
|
|
|
|
// split file |
|
let head = bytes.slice(0, 10); |
|
let tail = bytes.slice(10, bytes.length); // 10 -> 11 plugin wird verifiziert, lässt sich aber nicht mehr öffnen! |
|
|
|
|
|
|
|
let content = Buffer.concat([ |
|
head, |
|
EXTRA_HEADER, |
|
tail |
|
]); |
|
|
|
fs.writeFileSync("./plugin-signed.tgz", content); |
|
//console.log(EXTRA_HEADER[0], EXTRA_HEADER[1]) |
|
|
|
|
|
}); |