slonm / crypto-js

Automatically exported from code.google.com/p/crypto-js
0 stars 0 forks source link

Trouble decrypting a TripleDES hex string with an IV #116

Open GoogleCodeExporter opened 9 years ago

GoogleCodeExporter commented 9 years ago
I have a Java server creating a TripleDES-encrypted hex string using CFB and no 
padding ("DESede/CFB/NoPadding").  The first 16 bytes of the returned string 
are the IV, the rest is the encrypted message.  I have months-old ActionScript 
production code that successfully decrypts these messages (see code below).  I 
am trying to port this decryption code to a Node.js server, and haven't had any 
luck thus far.

I can't change the Java-side encryption, so I'm stuck with getting decryption 
to work somehow with the parameters outlined above.

-- 

What steps will reproduce the problem?
- This problem isn't directly reproducible, but:
1. I'm just trying to figure out what code to write with crypto-js to do the 
same thing that works in ActionScript. 
2. I've tried several different ways to write the JS code, and I get garbled 
messages every time.
3. I've looked for guidance in your examples, third-party blog entries, 
StackOverflow, and your unit tests.  There is a lot of talk about how to 
encrypt with a custom IV, but I can't find examples of decrypting with a known 
IV.

What is the expected output? What do you see instead?
- I expect to be able to decrypt my message given an IV, an encrypted message, 
and a shared secret key.

What version of the product are you using? On what operating system?
- NPM tells me I am running crypto-js@3.1.2-2.  Currently developing and 
testing on Windows 7 on a node.js server.

Please provide any additional information below.

Here is the ActionScript 3 code that works (using AS3Crypto):

  private function decryptFrom(encrypted:String):String {
    var mode:CFBMode = new CFBMode(new TripleDESKey(Hex.toArray("<hex shared secret here>")));
    mode.IV = Hex.toArray(encrypted.substr(0, 16));

    var data:ByteArray = Hex.toArray(encrypted.substr(16));
    mode.decrypt(data);

    return Hex.toString(Hex.fromArray(data));
  }

Here is just the latest of many, many attempts in JavaScript (CoffeeScript, 
actually, but you get the idea):

  _decryptFrom: (encrypted) ->
    sharedSecret = '<hex shared secret here>'
    hexStringArray = encrypted.split ''
    iv = hexStringArray[0..15].join('')
    ciphertext = hexStringArray[16..].join('')

    # This is just something I tried given a similar issue you answered about AES with IV's.  Outdated solution, as it was from 2011?
    ciphertextObj = new CryptoJS.Ciphertext(CryptoJS.util.hexToBytes(ciphertext), CryptoJS.util.hexToBytes(iv))

    CryptoJS.TripleDES.decrypt(ciphertextObj, sharedSecret, mode: CryptoJS.mode.CFB, padding: CryptoJS.pad.NoPadding).toString(CryptoJS.enc.Latin1)

I've also tried adding the IV to the options hash.  I've tried several 
combinations of converting the iv, ciphertext, and shared secret (key) from hex 
to word arrays.

I've also tried writing a formatter a few different ways, but I can't get that 
to work either:

customformatter =
  stringify: (cipherParams) ->
    cipherParams.iv.toString(CryptoJS.enc.hex) + cipherParams.ciphertext.toString(CryptoJS.enc.hex)

  parse: (hexString) ->
    hexStringArray = hexString.split '' 

    CryptoJS.lib.CipherParams.create
      iv: CryptoJS.enc.Hex.parse hexStringArray[0..15].join('')
      ciphertext: CryptoJS.enc.Hex.parse hexStringArray[16..].join('')

(I realize I'm not using stringify() for decryption -- I will be encrypting 
from this app as well, but I'm just trying to decrypt an existing message from 
Java first.)

So:  Can you give me some crypto-js decryption code that should be the 
equivalent of my working ActionScript code?

What I'd really love to see is a couple more tests added to your TripleDES test 
suite.  One that encrypts (without creating a custom IV) and returns an "IV + 
ciphertext" string, and one that decrypts that result, given only that "IV + 
ciphertext" string and the shared secret.

Thanks,
Ed

Original issue reported on code.google.com by ed.tram...@gmail.com on 10 Feb 2014 at 5:17

GoogleCodeExporter commented 9 years ago
Well, never mind and thanks anyway...  I gave up on crypto-js, and went back to 
Node.js's built-in crypto library (which I gave up on previously because I 
mistakenly thought it wouldn't handle CFB, but it does).

Perhaps you'll want to answer my query anyway, in case it helps some of your 
other users in the future.  (Besides, I'd like to see how close I was to 
getting this to work with your library.)

But for those who are stuck like I was, and get here via a search, here is my 
Node.js-crypto-based (repeat, NOT crypto-js-based!) code.  It decrypts its own 
encryptions, as well as the ones from my Java server.  (Whew.)

  sharedSecret = '<hex shared secret here>' 

  _encrypt: (string) ->
    randomIV = @_generateRandomHexString 16    

    cipher = crypto.createCipheriv 'des-ede3-cfb', new Buffer(sharedSecret, 'hex'), new Buffer(randomIV, 'hex')
    randomIV + cipher.update(string, 'utf8', 'hex') + cipher.final('hex')

  _decrypt: (encrypted) ->
    hexStringArray = encrypted.split ''
    iv = hexStringArray[0..15].join('')
    ciphertext = hexStringArray[16..].join('')

    decipher = crypto.createDecipheriv 'des-ede3-cfb', new Buffer(sharedSecret, 'hex'), new Buffer(iv, 'hex')
    decipher.update(ciphertext, 'hex', 'utf8') + decipher.final('utf8')

Thanks,
Ed

Original comment by ed.tram...@gmail.com on 10 Feb 2014 at 11:22