wouldgo / twofish

Twofish (ECB and CBC) javascript implementation
MIT License
31 stars 7 forks source link

Corrupted data on decryption #5

Open vitonsky opened 1 year ago

vitonsky commented 1 year ago

Hi, thanks for implement the algorithm on JS.

I found a bug. When i encrypt and then decrypt text, result string is not exact equal to a original string.

JSFiddle: https://jsfiddle.net/u3xohay0/

var tf = twofish();
var key1 = tf.stringToByteArray('secret');
var sourceText = 'Hello world 123 4 5';
var encBytes = tf.encryptCBC(key1, tf.stringToByteArray(sourceText));
var decText = tf.byteArrayToString(tf.decryptCBC(key1, encBytes));

decText // Hello world 123 4 5\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000

image


It looks like some padding bits, how to remove it? Keep in mind that we can't just remove 0-bits, because it may be part of source data.

digoni commented 4 months ago

I have this issue too. Do you have any solution for this ? Seems that the sourceText length must be multiple of 16 to work. I've tried with sourceText = '1234567890123456' or sourceText = '12345678901234561234567890123456' both work OK, but when the text length is not multiple of 16 the result is image

vitonsky commented 4 months ago

I have this issue too. Do you have any solution for this ?

I just use https://github.com/gliese1337/twofish instead. There pretty nice API

digoni commented 4 months ago

I found the solution. When the string to be encoded don't have lenght multiple of 16, we need to fill with white spaces (ASCII 32) and when decode use .trim() to achieve the same string.

Also is preferable that the key length have multiple of 16 too. I put a random hex key with length 32 on the code.

Here is an example

const { twofish } = require('twofish');
const tf = twofish();

var key         = Buffer.from('3c910a396b5aff83eb0f77579c4f661', 'hex');
var sourceText  = 'Text to be encrypted whith length not multiple of 16'; //This string length is 52 
var sourceBytes = Buffer.from(sourceText);

var sourceCopy  = fixBytes(sourceBytes);

var encBytes = tf.encrypt(key, sourceCopy);
var encText = Buffer.from(encBytes).toString('base64');
console.log(encText); //encrypted result converted to base64

var decText = Buffer.from(tf.decrypt(key, encBytes)).toString().trim();
console.log(decText); //back to original sourceText decrypted with .trim()

function fixBytes(srcByt = []) {
    let srcFixed = [];
    if (srcByt.length % 16 !== 0) {
        let rest = 16 - ((srcByt.length) % 16);
        for (i = 0; i < srcByt.length; i++) {
            srcFixed[i] = srcByt[i];
        }
        for (i = 0; i < rest; i++) {
            srcFixed[srcByt.length + i] = 32; //Fill with white spaces
        }
    } else {
        srcFixed = srcByt;
    };
    return srcFixed;
};