Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,7 @@
"jimp": "^0.22.12",
"jq-web": "^0.5.1",
"jquery": "3.7.1",
"js-ascon": "^1.3.0",
"js-sha3": "^0.9.3",
"jsesc": "^3.0.2",
"json5": "^2.2.3",
Expand Down
4 changes: 4 additions & 0 deletions src/core/config/Categories.json
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,8 @@
"Rabbit",
"SM4 Encrypt",
"SM4 Decrypt",
"Ascon Encrypt",
"Ascon Decrypt",
"GOST Encrypt",
"GOST Decrypt",
"GOST Sign",
Expand Down Expand Up @@ -427,6 +429,8 @@
"BLAKE2b",
"BLAKE2s",
"BLAKE3",
"Ascon Hash",
"Ascon MAC",
"GOST Hash",
"Streebog",
"SSDEEP",
Expand Down
112 changes: 112 additions & 0 deletions src/core/operations/AsconDecrypt.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
/**
* @author Medjedtxm

Check warning on line 2 in src/core/operations/AsconDecrypt.mjs

View workflow job for this annotation

GitHub Actions / main

Trailing spaces not allowed

Check warning on line 2 in src/core/operations/AsconDecrypt.mjs

View workflow job for this annotation

GitHub Actions / main

Trailing spaces not allowed
* @copyright Crown Copyright 2025
* @license Apache-2.0
*/

import Operation from "../Operation.mjs";
import OperationError from "../errors/OperationError.mjs";
import Utils from "../Utils.mjs";
import { toHexFast } from "../lib/Hex.mjs";
import JsAscon from "js-ascon";

/**
* Ascon Decrypt operation
*/
class AsconDecrypt extends Operation {

/**
* AsconDecrypt constructor
*/
constructor() {
super();

this.name = "Ascon Decrypt";
this.module = "Ciphers";
this.description = "Ascon-AEAD128 authenticated decryption as standardised in NIST SP 800-232. Decrypts ciphertext and verifies the authentication tag. Decryption will fail if the ciphertext or associated data has been tampered with.<br><br><b>Key:</b> Must be exactly 16 bytes (128 bits).<br><br><b>Nonce:</b> Must be exactly 16 bytes (128 bits). Must match the nonce used during encryption.<br><br><b>Associated Data:</b> Must match the associated data used during encryption. Any mismatch will cause authentication failure.";
this.infoURL = "https://wikipedia.org/wiki/Ascon_(cipher)";
this.inputType = "string";
this.outputType = "string";
this.args = [
{
"name": "Key",
"type": "toggleString",
"value": "",
"toggleValues": ["Hex", "UTF8", "Latin1", "Base64"]
},
{
"name": "Nonce",
"type": "toggleString",
"value": "",
"toggleValues": ["Hex", "UTF8", "Latin1", "Base64"]
},
{
"name": "Associated Data",
"type": "toggleString",
"value": "",
"toggleValues": ["Hex", "UTF8", "Latin1", "Base64"]
},
{
"name": "Input",
"type": "option",
"value": ["Hex", "Raw"]
},
{
"name": "Output",
"type": "option",
"value": ["Raw", "Hex"]
}
];
}

/**
* @param {string} input
* @param {Object[]} args
* @returns {string}
* @throws {OperationError} if invalid key or nonce length, or authentication fails
*/
run(input, args) {
const key = Utils.convertToByteArray(args[0].string, args[0].option),
nonce = Utils.convertToByteArray(args[1].string, args[1].option),
ad = Utils.convertToByteArray(args[2].string, args[2].option),
inputType = args[3],
outputType = args[4];

if (key.length !== 16) {
throw new OperationError(`Invalid key length: ${key.length} bytes.

Ascon-AEAD128 requires a key of exactly 16 bytes (128 bits).`);
}

if (nonce.length !== 16) {
throw new OperationError(`Invalid nonce length: ${nonce.length} bytes.

Ascon-AEAD128 requires a nonce of exactly 16 bytes (128 bits).`);
}

// Convert input to byte array
const inputData = Utils.convertToByteArray(input, inputType);

const keyUint8 = new Uint8Array(key);
const nonceUint8 = new Uint8Array(nonce);
const adUint8 = new Uint8Array(ad);
const ciphertextUint8 = new Uint8Array(inputData);

try {
// Decrypt (returns Uint8Array containing plaintext)
const plaintext = JsAscon.decrypt(keyUint8, nonceUint8, adUint8, ciphertextUint8);

// Return in requested format
if (outputType === "Hex") {
return toHexFast(plaintext);
} else {
return Utils.arrayBufferToStr(Uint8Array.from(plaintext).buffer);
}
} catch (e) {
throw new OperationError("Unable to decrypt: authentication failed. The ciphertext, key, nonce, or associated data may be incorrect or tampered with.");
}
}

}

export default AsconDecrypt;
108 changes: 108 additions & 0 deletions src/core/operations/AsconEncrypt.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
/**
* @author Medjedtxm
* @copyright Crown Copyright 2025
* @license Apache-2.0
*/

import Operation from "../Operation.mjs";
import OperationError from "../errors/OperationError.mjs";
import Utils from "../Utils.mjs";
import { toHexFast } from "../lib/Hex.mjs";
import JsAscon from "js-ascon";

/**
* Ascon Encrypt operation
*/
class AsconEncrypt extends Operation {

/**
* AsconEncrypt constructor
*/
constructor() {
super();

this.name = "Ascon Encrypt";
this.module = "Ciphers";
this.description = "Ascon-AEAD128 authenticated encryption as standardised in NIST SP 800-232. Ascon is a family of lightweight authenticated encryption algorithms designed for constrained devices such as IoT sensors and embedded systems.<br><br><b>Key:</b> Must be exactly 16 bytes (128 bits).<br><br><b>Nonce:</b> Must be exactly 16 bytes (128 bits). Should be unique for each encryption with the same key. Never reuse a nonce with the same key.<br><br><b>Associated Data:</b> Optional additional data that is authenticated but not encrypted. Useful for including metadata like headers or timestamps.<br><br>The output includes both the ciphertext and a 128-bit authentication tag.";
this.infoURL = "https://wikipedia.org/wiki/Ascon_(cipher)";
this.inputType = "string";
this.outputType = "string";
this.args = [
{
"name": "Key",
"type": "toggleString",
"value": "",
"toggleValues": ["Hex", "UTF8", "Latin1", "Base64"]
},
{
"name": "Nonce",
"type": "toggleString",
"value": "",
"toggleValues": ["Hex", "UTF8", "Latin1", "Base64"]
},
{
"name": "Associated Data",
"type": "toggleString",
"value": "",
"toggleValues": ["Hex", "UTF8", "Latin1", "Base64"]
},
{
"name": "Input",
"type": "option",
"value": ["Raw", "Hex"]
},
{
"name": "Output",
"type": "option",
"value": ["Hex", "Raw"]
}
];
}

/**
* @param {string} input
* @param {Object[]} args
* @returns {string}
* @throws {OperationError} if invalid key or nonce length
*/
run(input, args) {
const key = Utils.convertToByteArray(args[0].string, args[0].option),
nonce = Utils.convertToByteArray(args[1].string, args[1].option),
ad = Utils.convertToByteArray(args[2].string, args[2].option),
inputType = args[3],
outputType = args[4];

if (key.length !== 16) {
throw new OperationError(`Invalid key length: ${key.length} bytes.

Ascon-AEAD128 requires a key of exactly 16 bytes (128 bits).`);
}

if (nonce.length !== 16) {
throw new OperationError(`Invalid nonce length: ${nonce.length} bytes.

Ascon-AEAD128 requires a nonce of exactly 16 bytes (128 bits).`);
}

// Convert input to byte array
const inputData = Utils.convertToByteArray(input, inputType);

const keyUint8 = new Uint8Array(key);
const nonceUint8 = new Uint8Array(nonce);
const adUint8 = new Uint8Array(ad);
const inputUint8 = new Uint8Array(inputData);

// Encrypt (returns Uint8Array containing ciphertext + tag)
const ciphertext = JsAscon.encrypt(keyUint8, nonceUint8, adUint8, inputUint8);

// Return in requested format
if (outputType === "Hex") {
return toHexFast(ciphertext);
} else {
return Utils.arrayBufferToStr(Uint8Array.from(ciphertext).buffer);
}
}

}

export default AsconEncrypt;
49 changes: 49 additions & 0 deletions src/core/operations/AsconHash.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
/**
* @author Medjedtxm

Check warning on line 2 in src/core/operations/AsconHash.mjs

View workflow job for this annotation

GitHub Actions / main

Trailing spaces not allowed

Check warning on line 2 in src/core/operations/AsconHash.mjs

View workflow job for this annotation

GitHub Actions / main

Trailing spaces not allowed
* @copyright Crown Copyright 2025
* @license Apache-2.0
*/

import Operation from "../Operation.mjs";
import { toHexFast } from "../lib/Hex.mjs";
import JsAscon from "js-ascon";

/**
* Ascon Hash operation
*/
class AsconHash extends Operation {

/**
* AsconHash constructor
*/
constructor() {
super();

this.name = "Ascon Hash";
this.module = "Crypto";
this.description = "Ascon-Hash256 produces a fixed 256-bit (32-byte) cryptographic hash as standardised in NIST SP 800-232. Ascon is a family of lightweight authenticated encryption and hashing algorithms designed for constrained devices such as IoT sensors and embedded systems.<br><br>The algorithm was selected by NIST in 2023 as the new standard for lightweight cryptography after a multi-year competition.";
this.infoURL = "https://wikipedia.org/wiki/Ascon_(cipher)";
this.inputType = "ArrayBuffer";
this.outputType = "string";
this.args = [];
}

/**
* @param {ArrayBuffer} input
* @param {Object[]} args
* @returns {string}
*/
run(input, args) {

const inputUint8 = new Uint8Array(input);

// Compute hash (returns Uint8Array)
const hashResult = JsAscon.hash(inputUint8);

// Convert to hex string
return toHexFast(hashResult);
}

}

export default AsconHash;
68 changes: 68 additions & 0 deletions src/core/operations/AsconMAC.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
/**
* @author Medjedtxm
* @copyright Crown Copyright 2025
* @license Apache-2.0
*/

import Operation from "../Operation.mjs";
import OperationError from "../errors/OperationError.mjs";
import Utils from "../Utils.mjs";
import { toHexFast } from "../lib/Hex.mjs";
import AsconMac from "../vendor/ascon.mjs";

/**
* Ascon MAC operation
*/
class AsconMAC extends Operation {

/**
* AsconMAC constructor
*/
constructor() {
super();

this.name = "Ascon MAC";
this.module = "Crypto";
this.description = "Ascon-Mac produces a 128-bit (16-byte) message authentication code as part of the Ascon family standardised by NIST in SP 800-232. It provides authentication for messages using a secret key, ensuring both data integrity and authenticity.<br><br>Ascon is designed for lightweight cryptography on constrained devices such as IoT sensors and embedded systems.";
this.infoURL = "https://wikipedia.org/wiki/Ascon_(cipher)";
this.inputType = "ArrayBuffer";
this.outputType = "string";
this.args = [
{
"name": "Key",
"type": "toggleString",
"value": "",
"toggleValues": ["Hex", "UTF8", "Latin1", "Base64"]
}
];
}

/**
* @param {ArrayBuffer} input
* @param {Object[]} args
* @returns {string}
* @throws {OperationError} if invalid key length
*/
run(input, args) {
const keyArray = Utils.convertToByteArray(args[0].string, args[0].option);

if (keyArray.length !== 16) {
throw new OperationError(`Invalid key length: ${keyArray.length} bytes.

Ascon-Mac requires a key of exactly 16 bytes (128 bits).`);
}

// Convert to Uint8Array for vendor Ascon implementation
const keyUint8 = new Uint8Array(keyArray);
const inputUint8 = new Uint8Array(input);

// Compute MAC (returns Uint8Array)
const macResult = AsconMac.mac(keyUint8, inputUint8);

// Convert to hex string
return toHexFast(macResult);
}

}

export default AsconMAC;
Loading
Loading