2

I have files encrypted in C# (using DES, PKCS7). I need to decode these files in Node JS.

The code I use to decrypt in C# looks like this:

public string SSFile_Reader( string fileToDecrypt )
{
  DESCryptoServiceProvider provider = new DESCryptoServiceProvider
  {
    Key = Encoding.UTF8.GetBytes( "13^07v90" ),
    IV = Encoding.UTF8.GetBytes( "13^07v90" ),
    Padding = PaddingMode.PKCS7
  };
  
  using( FileStream streamToDecrypt = new FileStream( fileToDecrypt, FileMode.Open, FileAccess.Read, FileShare.ReadWrite ) )
  {
    ICryptoTransform cryptoTransform = provider.CreateDecryptor();
    string outputString = "";

    using( CryptoStream stream2 = new CryptoStream( streamToDecrypt, cryptoTransform, CryptoStreamMode.Read ) )
    {
      try
      {
        using( StreamReader reader = new StreamReader( stream2 ) )
        {
          try
          {
            outputString = reader.ReadToEnd();
          }
          catch
          {
           //handle error here
          }
          stream2.Close();
          streamToDecrypt.Close();

          return outputString;
        }
      }
      catch( Exception exception )
      {
        //handle error here
      }
    }
  }

  return '';
}

I literally need to convert the above to Node JS. I have tried the Node JS code below, but the output is just some random stuff rather than the original encrypted string:

const { Readable } = require("stream");
const { scrypt, scryptSync, randomFill, createCipheriv, createDecipheriv } = require('crypto');
const fs = require('fs');

const [, , pathToEncryptedFile] = process.argv;

if (!pathToEncryptedFile) {
  console.log('No file to decrypt')
  exit()
}

const keyAndIv = '31335e3037763930'; //hex equivalence of 13^07v90
const key = Buffer.from(keyAndIv, 'hex');
const iv = Buffer.from(keyAndIv, 'hex');

const decryptedData = '';

const decipher = createDecipheriv('des', key, iv);

const readableStream = Readable.from(fs.createReadStream(pathToEncryptedFile)
  .pipe(decipher));

readableStream.on("data", (chunk) => {
  decryptedData += chunk.toString()
})

readableStream.on('end', function () {
  console.log({decryptedData})
});

readableStream.on('error', function (err) {
  console.log({err})
});

I also tried using crypto-js to no avail (https://github.com/brix/crypto-js/issues/396).

This is an example of one of the files I need to decrypt: https://files.fm/u/6pewftkk2

I can also give the C# code that does the encryption if the C# code given above for the decryption does not suffice

8
  • ...I have tried below Node JS code:... And ... what happened? Commented Dec 28, 2021 at 14:38
  • ...the output is just some random stuff rather than the original encrypted string (sorry for the incomplete info. Question also updated) Commented Dec 28, 2021 at 14:45
  • The question is not clear, encoding is not encryption. Are you encoding or encrypting the file? Can you specify the algorithm you want to use? Commented Dec 28, 2021 at 14:48
  • Since you store the plaintext in outputString anyway, you can actually load the ciphertext directly without streams, e.g. with readFileSync() and decrypt the data with createDecipheriv(). For a larger ciphertext, which is read successively from the filesystem, and its resulting plaintext, which is written successively to the filesystem, pipe() would be a simple solution. Commented Dec 28, 2021 at 15:04
  • @Thecave3 Sorry for the error (I clearly said how to *decrypt*... so the encode was my error). Algo is DES with PKCS7 padding. This is the gist for the code that I use for the encryption Commented Dec 28, 2021 at 15:54

1 Answer 1

1

One possible variant is to load the ciphertext completely from the file system and decrypt it:

var crypto = require('crypto')
var fs = require('fs')

const algorithm = 'des'; // defaults to 'des-cbc';
const password = 'Password used to generate key';
const key = '13^07v90';
const iv = '13^07v90'; 

const ciphertext = fs.readFileSync('<path to high_classes.ssdata>');
const decipher = crypto.createDecipheriv(algorithm, key, iv);
const plaintext = decipher.update(ciphertext, '', 'utf8') + decipher.final();
console.log(plaintext);

which outputs the following plaintext (for the linked file):

SSS1
SSS2
SSS3

Alternatively, especially for large data, the plaintext can also be streamed to a file. To do this, replace the last block with:

const decipher = crypto.createDecipheriv(algorithm, key, iv);
const readStream = fs.createReadStream('<path to high_classes.ssdata>');
const writeStream = fs.createWriteStream('<path to file where decrypted data should be saved>');
readStream.pipe(decipher).pipe(writeStream);

which creates a file containing the decrypted data.


Note that DES is outdated and insecure these days. Using the key as an IV is also insecure. Typically, a random IV is generated during encryption and passed to the other side along with the ciphertext (usually concatenated).

Sign up to request clarification or add additional context in comments.

12 Comments

Thanks for your effort, @Topaco. When I tried the code you posted above, I get an error on the line const decipher = crypto.createDecipheriv(algorithm, key, iv). The error, summarily, is: node:internal/crypto/cipher:116 this[kHandle].initiv(cipher, credential, iv, authTagLength); ^ Error: error:0308010C:digital envelope routines::unsupported
I get your point with respect to DES being outdated. I wrote this code in 2015/2016. It's a really old codebase I am actually re-writing it with Node JS, and I am removing this file encryption feature entirely because in hindsight, it has not helped in any way to the service we use it for. If anything, it has made Customer support and ease of development a pain in the neck. Thanks for the heads-up though
I hope the error I am getting is not related to PKCS7 padding? Also, I should mention that I am using Node.js v17.0.1
I can't reproduce this issue. You can run the code online on replit: replit.com/@3hK8cL8H24hwiS7/GrowlingValuablePriorities. Since there is no access to the filesystem, the data must be imported from the file 2301...71d6 (hex encoded). Please run this code in your environment. If this works, check in your environment the imported ciphertext with const ciphertext = fs.readFileSync("<high_classes.ssdata>") and output it with console.log(ciphertext.toString('hex'));. It should correspond to 2301...71d6 and decryption should work.
So my error was actually about the legacy provider issue as you rightly mentioned. Thanks man, you saved my day!
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.