Merge branch 'qrcodes' of https://github.com/j433866/CyberChef into j433866-qrcodes

This commit is contained in:
n1474335 2018-12-25 19:07:59 +00:00
commit 4ee0800990
7 changed files with 289 additions and 0 deletions

View file

@ -92,6 +92,7 @@
"exif-parser": "^0.1.12", "exif-parser": "^0.1.12",
"file-saver": "^2.0.0-rc.4", "file-saver": "^2.0.0-rc.4",
"highlight.js": "^9.13.1", "highlight.js": "^9.13.1",
"jimp": "^0.6.0",
"jquery": "^3.3.1", "jquery": "^3.3.1",
"js-crc": "^0.2.0", "js-crc": "^0.2.0",
"js-sha3": "^0.8.0", "js-sha3": "^0.8.0",
@ -99,6 +100,7 @@
"jsesc": "^2.5.1", "jsesc": "^2.5.1",
"jsonpath": "^1.0.0", "jsonpath": "^1.0.0",
"jsonwebtoken": "^8.3.0", "jsonwebtoken": "^8.3.0",
"jsqr": "^1.1.1",
"jsrsasign": "8.0.12", "jsrsasign": "8.0.12",
"kbpgp": "^2.0.82", "kbpgp": "^2.0.82",
"lodash": "^4.17.11", "lodash": "^4.17.11",
@ -113,6 +115,7 @@
"nwmatcher": "^1.4.4", "nwmatcher": "^1.4.4",
"otp": "^0.1.3", "otp": "^0.1.3",
"popper.js": "^1.14.4", "popper.js": "^1.14.4",
"qr-image": "^3.2.0",
"scryptsy": "^2.0.0", "scryptsy": "^2.0.0",
"snackbarjs": "^1.1.0", "snackbarjs": "^1.1.0",
"sortablejs": "^1.7.0", "sortablejs": "^1.7.0",

View file

@ -363,6 +363,8 @@
"Generate UUID", "Generate UUID",
"Generate TOTP", "Generate TOTP",
"Generate HOTP", "Generate HOTP",
"Generate QR Code",
"Parse QR Code",
"Haversine distance", "Haversine distance",
"Numberwang", "Numberwang",
"XKCD Random Number" "XKCD Random Number"

View file

@ -0,0 +1,104 @@
/**
* @author j433866 [j433866@gmail.com]
* @copyright Crown Copyright 2018
* @license Apache-2.0
*/
import Operation from "../Operation";
import OperationError from "../errors/OperationError";
import qr from "qr-image";
import { toBase64 } from "../lib/Base64";
import Magic from "../lib/Magic";
/**
* Generate QR Code operation
*/
class GenerateQRCode extends Operation {
/**
* GenerateQRCode constructor
*/
constructor() {
super();
this.name = "Generate QR Code";
this.module = "Image";
this.description = "Generates a QR code from text.";
this.infoURL = "https://wikipedia.org/wiki/QR_code";
this.inputType = "string";
this.outputType = "byteArray";
this.presentType = "html";
this.args = [
{
"name": "Image Format",
"type": "option",
"value": ["PNG", "SVG"]
},
{
"name": "Size of QR module",
"type": "number",
"value": 5
},
{
"name": "Margin",
"type": "number",
"value": 2
}
];
}
/**
* @param {string} input
* @param {Object[]} args
* @returns {File}
*/
run(input, args) {
// Create new QR image from the input data, and convert it to a buffer
const [format, size, margin] = args;
const qrImage = qr.imageSync(input, { type: format, size: size, margin: margin });
if (qrImage == null) {
throw new OperationError("Error generating QR code.");
}
if (format === "SVG") {
return [...Buffer.from(qrImage)];
} else if (format === "PNG") {
// Return the QR image buffer as a byte array
return [...qrImage];
} else {
throw new OperationError("Error generating QR code.");
}
}
/**
* Displays the QR image using HTML for web apps
*
* @param {byteArray} data
* @returns {html}
*/
present(data, args) {
if (!data.length) return "";
const [format] = args;
if (format === "SVG") {
let outputData = "";
for (let i = 0; i < data.length; i++){
outputData += String.fromCharCode(parseInt(data[i]));
}
return outputData;
} else {
let dataURI = "data:";
const type = Magic.magicFileType(data);
if (type && type.mime.indexOf("image") === 0){
dataURI += type.mime + ";";
} else {
throw new OperationError("Invalid file type");
}
dataURI += "base64," + toBase64(data);
return "<img src='" + dataURI + "'>";
}
}
}
export default GenerateQRCode;

View file

@ -0,0 +1,105 @@
/**
* @author j433866 [j433866@gmail.com]
* @copyright Crown Copyright 2018
* @license Apache-2.0
*/
import Operation from "../Operation";
import OperationError from "../errors/OperationError";
import Magic from "../lib/Magic";
import jsqr from "jsqr";
import jimp from "jimp";
/**
* Parse QR Code operation
*/
class ParseQRCode extends Operation {
/**
* ParseQRCode constructor
*/
constructor() {
super();
this.name = "Parse QR Code";
this.module = "Image";
this.description = "Reads an image file and attempts to detect and read a QR code from the image.<br><br><u>Normalise Image</u><br>Attempt to normalise the image before parsing it, to try and improve detection of a QR code.";
this.infoURL = "https://wikipedia.org/wiki/QR_code";
this.inputType = "byteArray";
this.outputType = "string";
this.args = [
{
"name": "Normalise image",
"type": "boolean",
"value": true
}
];
}
/**
* @param {byteArray} input
* @param {Object[]} args
* @returns {string}
*/
async run(input, args) {
const type = Magic.magicFileType(input);
const [normalise] = args;
// Make sure that the input is an image
if (type && type.mime.indexOf("image") === 0){
let normalisedImage = null;
if (normalise){
// Process the image to be easier to read by jsqr
// Disables the alpha channel
// Sets the image default background to white
// Normalises the image colours
// Makes the image greyscale
// Converts image to a JPEG
normalisedImage = await new Promise((resolve, reject) => {
jimp.read(Buffer.from(input))
.then(image => {
image
.rgba(false)
.background(0xFFFFFFFF)
.normalize()
.greyscale()
.getBuffer(jimp.MIME_JPEG, (error, result) => {
resolve([...result]);
});
})
.catch(err => {
reject(new OperationError("Error reading the image file."));
});
});
} else {
normalisedImage = input;
}
if (normalisedImage instanceof OperationError){
return normalisedImage;
}
return new Promise((resolve, reject) => {
jimp.read(Buffer.from(normalisedImage))
.then(image => {
if (image.bitmap != null){
const qrData = jsqr(image.bitmap.data, image.getWidth(), image.getHeight());
if (qrData != null){
resolve(qrData.data);
} else {
reject(new OperationError("Couldn't read a QR code from the image."));
}
} else {
reject(new OperationError("Error reading the normalised image file."));
}
})
.catch(err => {
reject(new OperationError("Error reading the normalised image file."));
});
});
} else {
throw new OperationError("Invalid file type.");
}
}
}
export default ParseQRCode;

View file

@ -64,6 +64,7 @@ import "./tests/operations/OTP";
import "./tests/operations/PGP"; import "./tests/operations/PGP";
import "./tests/operations/PHP"; import "./tests/operations/PHP";
import "./tests/operations/ParseIPRange"; import "./tests/operations/ParseIPRange";
import "./tests/operations/ParseQRCode";
import "./tests/operations/PowerSet"; import "./tests/operations/PowerSet";
import "./tests/operations/Regex"; import "./tests/operations/Regex";
import "./tests/operations/Register"; import "./tests/operations/Register";

File diff suppressed because one or more lines are too long

View file

@ -46,6 +46,9 @@ module.exports = {
raw: true, raw: true,
entryOnly: true entryOnly: true
}), }),
new webpack.DefinePlugin({
"process.browser": "true"
}),
vendorCSS, vendorCSS,
projectCSS projectCSS
], ],