0

We are using the SJCL (Stanford Javascript Crypto Library) to encrypt in JavaScript and we are supposed to implement decryption in Java.

The encryption code looks like this:

<script src='https://cdnjs.cloudflare.com/ajax/libs/sjcl/1.0.7/sjcl.js'></script>

<script>
var keyString = '2d73c1dd2f6a3c981afc7c0d49d7b58f';
var key = sjcl.codec.base64.toBits(keyString);
var cipher = new sjcl.cipher.aes(key)
var data = sjcl.codec.utf8String.toBits('Hello Crypto!'); 
var salt = sjcl.codec.base64url.toBits('kLME6vN-WdU_W9XVN9a1Z3E_p8HQ5C7X1La-3ZjEml1ytVRMfvtEXzeapbce2LjFI1dHEGtWv9bZ_U6K2CG1-K4lQPunFXWxXmsTQIXlGfwmpveg2AFeLFiqGmALnfbP');
var encrypted = sjcl.encrypt(keyString,'Hello Crypto!',{mode:'gcm',salt:salt});

console.log(encrypted)
</script>

The resulting encryption looks like the following:

{
   "iv":"+xmg3yZF/LSWNFpXf03wUw==",
   "v":1,
   "iter":10000,
   "ks":128,
   "ts":64,
   "mode":"gcm",
   "adata":"",
   "cipher":"aes",
   "salt":"kLME6vN+WdU/W9XVN9a1Z3E/p8HQ5C7X1La+3ZjEml1ytVRMfvtEXzeapbce2LjFI1dHEGtWv9bZ/U6K2CG1+K4lQPunFXWxXmsTQIXlGfwmpveg2AFeLFiqGmALnfbP",
   "ct":"Nq+9tXfc0zs0/m3OfDp0MmTXc9qD"
}

We were supplied with sample Java code to decrypt the code but this code assumes that IV and salt is the same thing so it won't work with the JSON that we are getting from the JS lib (having IV and salt as two separate values):

 final byte[] symKeyData = DatatypeConverter.parseHexBinary(keyHex);
 final byte[] ivData = ivSalt.getBytes(Charset.forName("UTF-8"));
 final byte[] encryptedMessage = DatatypeConverter.parseBase64Binary(encryptedMessageString);
 final Cipher cipher = javax.crypto.Cipher.getInstance("AES/GCM/NoPadding", "BC");
 final SecretKeySpec symKey = new SecretKeySpec(symKeyData, "AES");
 final IvParameterSpec iv = new IvParameterSpec(ivData);
 cipher.init(Cipher.DECRYPT_MODE, symKey, iv);
 final byte[] encodedMessage = cipher.doFinal(encryptedMessage);
 final String message = new String(encodedMessage, Charset.forName("UTF-8"));

Can anybody explain how the resulting JSON from the JavaScript library can be decrypted correctly in Java?

B.E.
  • 5,080
  • 4
  • 35
  • 43

1 Answers1

3

SJCL convenience libs use PBKDF2 with 1000 iterations to derive the key. The documentation and code can be found here.

However, if this is an assignment:

  • the IV is the wrong size, it should be 12 bytes, not 16;
  • the salt size is way too large;
  • the cipher variable in the JavaScript is entirely ignored;
  • the iteration count is left at the default, which is normally considered too low.

So I don't know who wrote it, but they should not be releasing such code.

The salt is used for PBKDF2, the IV is for the symmetric cipher, so they are not the same.

Maarten Bodewes
  • 90,524
  • 13
  • 150
  • 263
  • 1
    I agree with Maarten, this is not good code and should not be used or shared for fear someone would use it. Ill add that on the client side SJCL really shouldn't be used in a production application either, today you would use WebCrypto for the client side. – rmhrisk Nov 10 '17 at 05:05
  • The tag length, 64 bits, is also nonstandard and not supported by the Oracle providers. It seems to be supported by Bouncycastle but regardless I could not decrypt the ciphertext. – President James K. Polk Nov 15 '17 at 02:30
  • @JamesKPolk Are you sure about the tag size? 64 bit is explicitly mentioned [here](https://docs.oracle.com/javase/7/docs/api/javax/crypto/spec/GCMParameterSpec.html) – Maarten Bodewes Nov 15 '17 at 10:36
  • 2
    Here's the exception I got: `java.security.InvalidAlgorithmParameterException: Unsupported TLen value; must be one of {128, 120, 112, 104, 96}` – President James K. Polk Nov 15 '17 at 11:55