Skip to content

Commit

Permalink
Merge pull request #501 from kassi/fernet
Browse files Browse the repository at this point in the history
Add Fernet encryption/decryption operation
  • Loading branch information
a3957273 authored Feb 22, 2024
2 parents bebb216 + 210186e commit c4e7c41
Show file tree
Hide file tree
Showing 7 changed files with 216 additions and 1 deletion.
15 changes: 15 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 @@ -122,6 +122,7 @@
"escodegen": "^2.1.0",
"esprima": "^4.0.1",
"exif-parser": "^0.1.12",
"fernet": "^0.3.2",
"file-saver": "^2.0.5",
"flat": "^6.0.1",
"geodesy": "1.1.3",
Expand Down
2 changes: 2 additions & 0 deletions src/core/config/Categories.json
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,8 @@
"DES Decrypt",
"Triple DES Encrypt",
"Triple DES Decrypt",
"Fernet Encrypt",
"Fernet Decrypt",
"LS47 Encrypt",
"LS47 Decrypt",
"RC2 Encrypt",
Expand Down
63 changes: 63 additions & 0 deletions src/core/operations/FernetDecrypt.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
/**
* @author Karsten Silkenbäumer [github.com/kassi]
* @copyright Karsten Silkenbäumer 2019
* @license Apache-2.0
*/

import Operation from "../Operation.mjs";
import OperationError from "../errors/OperationError.mjs";
import fernet from "fernet";

/**
* FernetDecrypt operation
*/
class FernetDecrypt extends Operation {
/**
* FernetDecrypt constructor
*/
constructor() {
super();

this.name = "Fernet Decrypt";
this.module = "Default";
this.description = "Fernet is a symmetric encryption method which makes sure that the message encrypted cannot be manipulated/read without the key. It uses URL safe encoding for the keys. Fernet uses 128-bit AES in CBC mode and PKCS7 padding, with HMAC using SHA256 for authentication. The IV is created from os.random().<br><br><b>Key:</b> The key must be 32 bytes (256 bits) encoded with Base64.";
this.infoURL = "https://asecuritysite.com/encryption/fer";
this.inputType = "string";
this.outputType = "string";
this.args = [
{
"name": "Key",
"type": "string",
"value": ""
},
];
this.patterns = [
{
match: "^[A-Z\\d\\-_=]{20,}$",
flags: "i",
args: []
},
];
}
/**
* @param {String} input
* @param {Object[]} args
* @returns {String}
*/
run(input, args) {
const [secretInput] = args;
try {
const secret = new fernet.Secret(secretInput);
const token = new fernet.Token({
secret: secret,
token: input,
ttl: 0
});
return token.decode();
} catch (err) {
throw new OperationError(err);
}
}
}

export default FernetDecrypt;
54 changes: 54 additions & 0 deletions src/core/operations/FernetEncrypt.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
/**
* @author Karsten Silkenbäumer [github.com/kassi]
* @copyright Karsten Silkenbäumer 2019
* @license Apache-2.0
*/

import Operation from "../Operation.mjs";
import OperationError from "../errors/OperationError.mjs";
import fernet from "fernet";

/**
* FernetEncrypt operation
*/
class FernetEncrypt extends Operation {
/**
* FernetEncrypt constructor
*/
constructor() {
super();

this.name = "Fernet Encrypt";
this.module = "Default";
this.description = "Fernet is a symmetric encryption method which makes sure that the message encrypted cannot be manipulated/read without the key. It uses URL safe encoding for the keys. Fernet uses 128-bit AES in CBC mode and PKCS7 padding, with HMAC using SHA256 for authentication. The IV is created from os.random().<br><br><b>Key:</b> The key must be 32 bytes (256 bits) encoded with Base64.";
this.infoURL = "https://asecuritysite.com/encryption/fer";
this.inputType = "string";
this.outputType = "string";
this.args = [
{
"name": "Key",
"type": "string",
"value": ""
},
];
}
/**
* @param {String} input
* @param {Object[]} args
* @returns {String}
*/
run(input, args) {
const [secretInput] = args;
try {
const secret = new fernet.Secret(secretInput);
const token = new fernet.Token({
secret: secret,
});
return token.encode(input);
} catch (err) {
throw new OperationError(err);
}
}
}

export default FernetEncrypt;
2 changes: 1 addition & 1 deletion tests/node/tests/nodeApi.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -136,7 +136,7 @@ TestRegister.addApiTests([

it("chef.help: returns multiple results", () => {
const result = chef.help("base 64");
assert.strictEqual(result.length, 11);
assert.strictEqual(result.length, 13);
}),

it("chef.help: looks in description for matches too", () => {
Expand Down
80 changes: 80 additions & 0 deletions tests/operations/tests/Fernet.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
/**
* Fernet tests.
*
* @author Karsten Silkenbäumer [github.com/kassi]
* @copyright Karsten Silkenbäumer 2019
* @license Apache-2.0
*/
import TestRegister from "../TestRegister";

TestRegister.addTests([
{
name: "Fernet Decrypt: no input",
input: "",
expectedOutput: "Error: Invalid version",
recipeConfig: [
{
op: "Fernet Decrypt",
args: ["MTIzNDU2Nzg5MDEyMzQ1Njc4OTAxMjM0NTY3ODkwMTI="]
}
],
},
{
name: "Fernet Decrypt: no secret",
input: "gAAAAABce-Tycae8klRxhDX2uenJ-uwV8-A1XZ2HRnfOXlNzkKKfRxviNLlgtemhT_fd1Fw5P_zFUAjd69zaJBQyWppAxVV00SExe77ql8c5n62HYJOnoIU=",
expectedOutput: "Error: Secret must be 32 url-safe base64-encoded bytes.",
recipeConfig: [
{
op: "Fernet Decrypt",
args: [""]
}
],
},
{
name: "Fernet Decrypt: valid arguments",
input: "gAAAAABce-Tycae8klRxhDX2uenJ-uwV8-A1XZ2HRnfOXlNzkKKfRxviNLlgtemhT_fd1Fw5P_zFUAjd69zaJBQyWppAxVV00SExe77ql8c5n62HYJOnoIU=",
expectedOutput: "This is a secret message.\n",
recipeConfig: [
{
op: "Fernet Decrypt",
args: ["VGhpc0lzVGhpcnR5VHdvQ2hhcmFjdGVyc0xvbmdLZXk="]
}
],
}
]);

TestRegister.addTests([
{
name: "Fernet Encrypt: no input",
input: "",
expectedMatch: /^gAAAAABce-[\w-]+={0,2}$/,
recipeConfig: [
{
op: "Fernet Encrypt",
args: ["MTIzNDU2Nzg5MDEyMzQ1Njc4OTAxMjM0NTY3ODkwMTI="]
}
],
},
{
name: "Fernet Encrypt: no secret",
input: "This is a secret message.\n",
expectedOutput: "Error: Secret must be 32 url-safe base64-encoded bytes.",
recipeConfig: [
{
op: "Fernet Encrypt",
args: [""]
}
],
},
{
name: "Fernet Encrypt: valid arguments",
input: "This is a secret message.\n",
expectedMatch: /^gAAAAABce-[\w-]+={0,2}$/,
recipeConfig: [
{
op: "Fernet Encrypt",
args: ["MTIzNDU2Nzg5MDEyMzQ1Njc4OTAxMjM0NTY3ODkwMTI="]
}
],
}
]);

0 comments on commit c4e7c41

Please sign in to comment.