🚀 Big News: Socket Acquires Coana to Bring Reachability Analysis to Every Appsec Team.Learn more
Socket
Book a DemoInstallSign in
Socket

feistel-cipher

Package Overview
Dependencies
Maintainers
2
Versions
48
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

feistel-cipher - npm Package Compare versions

Comparing version

to
1.4.0

dist/lib/src/typescript/utils/bytes.d.ts

32

dist/lib/src/typescript/fpe.d.ts

@@ -18,9 +18,23 @@ import { Readable } from './utils/base256';

/**
* Obfuscate the passed data
*
* @param {string} data - The data to obfuscate
* @returns {Readable} The byte array of the obfuscated result.
*/
* Obfuscate the passed data
*
* @param {string} data - The data to obfuscate
* @returns {Readable} The readable string of the obfuscated result.
*/
encrypt(data: string): Readable;
/**
* Obfuscate numbers
*
* @param {number} n - The data to obfuscate
* @returns {number} The obfuscated number.
*/
encryptNumber(n: number): number;
/**
*Obfuscate strings
*
* @param {string} str - The data to obfuscate
* @returns {Readable} The readable string of the obfuscated result.
*/
encryptString(str: string): Readable;
/**
* Deobfuscate the passed data

@@ -32,4 +46,12 @@ *

decrypt(obfuscated: Readable): string;
/**
* Deobfuscate the passed number
*
* @param {number} obfuscated - The number to use
* @returns {number} The deobfuscated number.
*/
decryptNumber(obfuscated: number): number;
private round;
private roundBytes;
}
//# sourceMappingURL=fpe.d.ts.map

@@ -27,2 +27,3 @@ "use strict";

const base256_1 = require("./utils/base256");
const bytes_1 = require("./utils/bytes");
const hash_1 = require("./utils/hash");

@@ -50,7 +51,7 @@ const strings_1 = require("./utils/strings");

/**
* Obfuscate the passed data
*
* @param {string} data - The data to obfuscate
* @returns {Readable} The byte array of the obfuscated result.
*/
* Obfuscate the passed data
*
* @param {string} data - The data to obfuscate
* @returns {Readable} The readable string of the obfuscated result.
*/
encrypt(data) {

@@ -80,2 +81,51 @@ let parts = (0, strings_1.split)(data);

/**
* Obfuscate numbers
*
* @param {number} n - The data to obfuscate
* @returns {number} The obfuscated number.
*/
encryptNumber(n) {
if (n < 256) {
if (n === 0) {
return 0;
}
const buf = Buffer.alloc(2);
buf.writeUInt16BE(n);
return (0, base256_1.readable2Buffer)(this.encrypt(buf.toString())).readUInt16BE();
}
let buf = Buffer.alloc(4);
buf.writeUInt32BE(n);
let parts = (0, bytes_1.splitBytes)(buf);
// Apply the FPE Feistel cipher
for (let i = 0; i < this.rounds; ++i) { // eslint-disable-line no-loops/no-loops
const left = parts[1];
if (parts[1].length < parts[0].length) {
parts[1] = Buffer.concat([parts[1], xor_1.NEUTRAL]);
}
const rnd = this.roundBytes(parts[1], i);
let tmp = parts[0];
let crop = false;
if (tmp.length + 1 === rnd.length) {
tmp = Buffer.concat([tmp, xor_1.NEUTRAL]);
crop = true;
}
let right = (0, xor_1.xorBytes)(tmp, rnd);
if (crop) {
right = right.fill(right, 0, right.length - 1, 'binary');
}
parts = [left, right];
}
buf = Buffer.concat([parts[0], parts[1]]);
return buf.readUInt32BE();
}
/**
*Obfuscate strings
*
* @param {string} str - The data to obfuscate
* @returns {Readable} The readable string of the obfuscated result.
*/
encryptString(str) {
return this.encrypt(str);
}
/**
* Deobfuscate the passed data

@@ -119,2 +169,52 @@ *

}
/**
* Deobfuscate the passed number
*
* @param {number} obfuscated - The number to use
* @returns {number} The deobfuscated number.
*/
decryptNumber(obfuscated) {
if (obfuscated === 0) {
return 0;
}
let buf = Buffer.alloc(2);
let short = true;
try {
buf.writeUInt16BE(obfuscated);
}
catch (e) {
buf = Buffer.alloc(4);
buf.writeUInt32BE(obfuscated);
short = false;
}
// Apply the FPE Feistel cipher
const parts = (0, bytes_1.splitBytes)(buf);
let [left, right] = parts;
// Compensating the way Split() works by moving the first byte at right to the end of left if using an odd number of rounds
if (this.rounds % 2 !== 0 && left.length !== right.length) {
left = Buffer.concat([left, Buffer.from([right[0]])]);
right = Buffer.alloc(0).fill(right, 1, undefined, 'binary');
}
for (let i = 0; i < this.rounds; ++i) { // eslint-disable-line no-loops/no-loops
let leftRound = left;
if (left.length < right.length) {
leftRound = Buffer.concat([leftRound, xor_1.NEUTRAL]);
}
const rnd = this.roundBytes(leftRound, this.rounds - i - 1);
let rightRound = right;
let extended = false;
if (rightRound.length + 1 === rnd.length) {
rightRound = Buffer.concat([rightRound, Buffer.alloc(0).fill(left, left.length - 1, undefined, 'binary')]);
extended = true;
}
let tmp = (0, xor_1.xorBytes)(rightRound, rnd);
right = left;
if (extended) {
tmp = Buffer.alloc(0).fill(tmp, 0, tmp.length - 1, 'binary');
}
left = tmp;
}
buf = Buffer.concat([left, right]);
return short ? buf.readUInt16BE() : buf.readUInt32BE();
}
// Feistel implementation

@@ -127,3 +227,10 @@ // Round is the function applied at each round of the obfuscation process to the right side of the Feistel cipher

}
// RoundBytes operates like round() on byte arrays
roundBytes(item, index) {
const addition = (0, bytes_1.addBytes)(item, (0, bytes_1.extractBytes)(Buffer.from(this.key), index, item.length));
const hashed = (0, hash_1.H)(addition, this.engine);
const extracted = (0, strings_1.extract)(hashed.toString('hex'), index, item.length);
return Buffer.from([...extracted].map(c => Buffer.from(c).readInt8()));
}
}
exports.FPECipher = FPECipher;

@@ -39,2 +39,6 @@ "use strict";

exports.SHA_3 = exports.SHA_256 = exports.KECCAK = exports.BLAKE2b = void 0;
if (typeof window !== 'undefined') {
// eslint-disable-next-line @typescript-eslint/strict-boolean-expressions,@typescript-eslint/no-unsafe-member-access,@typescript-eslint/no-var-requires
window.Buffer = window.Buffer || require('buffer').Buffer;
}
__exportStar(require("./feistel"), exports);

@@ -41,0 +45,0 @@ __exportStar(require("./fpe"), exports);

@@ -0,3 +1,6 @@

/// <reference types="node" />
export declare const xor: (str1: string, str2: string) => string;
export declare const xorBytes: (bytes1: Buffer, bytes2: Buffer) => Buffer;
export declare const NEUTRAL_BYTE: string;
export declare const NEUTRAL: Buffer;
//# sourceMappingURL=xor.d.ts.map

@@ -24,3 +24,3 @@ "use strict";

Object.defineProperty(exports, "__esModule", { value: true });
exports.NEUTRAL_BYTE = exports.xor = void 0;
exports.NEUTRAL = exports.NEUTRAL_BYTE = exports.xorBytes = exports.xor = void 0;
// xor applies XOR operation on two strings in the sense that each charCode are xored

@@ -31,2 +31,8 @@ const xor = (str1, str2) => {

exports.xor = xor;
// xorBytes applies XOR operation on thow byte arrays in the sense that each bit value are xored
const xorBytes = (bytes1, bytes2) => {
return Buffer.from(bytes1).reduce((xored, c, idx) => Buffer.concat([xored, Buffer.from([c ^ bytes2[idx]])]), Buffer.alloc(0));
};
exports.xorBytes = xorBytes;
exports.NEUTRAL_BYTE = Buffer.from([0]).toString();
exports.NEUTRAL = Buffer.from([0]);

14

package.json
{
"name": "feistel-cipher",
"version": "1.3.14",
"version": "1.4.0",
"description": "Feistel cipher implementation for format-preserving encryption",

@@ -39,10 +39,10 @@ "main": "dist/lib/src/typescript/index.js",

"@types/keccak": "^3.0.1",
"@types/mocha": "^9.1.1",
"@types/node": "^18.7.15",
"@typescript-eslint/eslint-plugin": "^5.36.2",
"@typescript-eslint/parser": "^5.36.2",
"@types/mocha": "^10.0.0",
"@types/node": "^18.8.5",
"@typescript-eslint/eslint-plugin": "^5.40.0",
"@typescript-eslint/parser": "^5.40.0",
"blakejs": "^1.2.1",
"browserify": "17.0.0",
"chai": "^4.3.6",
"eslint": "^8.23.0",
"eslint": "^8.25.0",
"eslint-plugin-no-loops": "~0.3.0",

@@ -53,3 +53,3 @@ "keccak": "^3.0.2",

"ts-node": "^10.9.1",
"typescript": "^4.8.2"
"typescript": "^4.8.4"
},

@@ -56,0 +56,0 @@ "resolutions": {

@@ -84,2 +84,11 @@ # feistel-cipher

If you want to use FPE for numbers, you might want to use the `encryptNumber()` method on the `FPECipher` which will return a number that you may pad if need be to match your requirements:
```typescript
const obfuscatedNumber = cipher.encryptNumber(sourceNumber)
const deobfuscatedNumber = cipher.decryptNumber(obfuscatedNumber)
assert(sourceNumber == deobfuscatedNumber)
```
_NB: For stability and security purposes, the number `0` always returns itself._
### Dependencies

@@ -86,0 +95,0 @@

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet