Error: CCM:Tag doesn't match

1,002 views
Skip to first unread message

Kevin McDowell

unread,
Aug 22, 2013, 5:24:49 PM8/22/13
to sjcl-d...@googlegroups.com
I have code that uses SJCL to encrypt and decrypt arrays of data.  It encrypts fine, but when it decrypts, I always get the error, "ccm: tag doesn't match". 
 
My code looks like this:
 
To encrypt:
          var p = "{\"iv\":\"9Xz/lNqbuATWz+H3viOAQA\",\"v\":1,\"iter\":1000,\"ks\":128,\"ts\":64,\"mode\":\"ccm\",\"adata\":\"\",\"cipher\":\"aes\",\"salt\":\"ItnNFEoD4vc\"}";
          var rp={};    
          var rawData = test.value[i][j];
          rawData = rawData.toString();
         
          var encrypted = sjcl.encrypt(password,  rawData, p, rp);
          encrypted = encrypted.match(/"ct":"([^"]*)"/)[1];

          
To decrypt:
          var encodedData = test.value[i][j];
          var coded = "{\"iv\":\"9Xz/lNqbuATWz+H3viOAQA\",\"v\":1,\"iter\":1000,\"ks\":128,\"ts\":64,\"mode\":\"ccm\",\"adata\":\"\",\"cipher\":\"aes\",\"salt\":\"ItnNFEoD4vc\",\"ct\":\"" + encodedData + "\"}" 
          var decrypted = sjcl.decrypt(password, coded);
 
Are the parameters passed in for the 3rd argument for sjcl.encrypt ignored?
 
The documentation header for encrypt states:
 
 13   /** Simple encryption function.
 14    * @param {String|bitArray} password The password or key.
 15    * @param {String} plaintext The data to encrypt.
 16    * @param {Object} [params] The parameters including tag, iv and salt.
 17    * @param {Object} [rp] A returned version with filled-in parameters.
 18    * @return {String} The ciphertext.
 19    * @throws {sjcl.exception.invalid} if a parameter is invalid.
 20    */
 
Based on that, I would expect it to use the parameters if they were passed in, but after debugging, it doesn't seem to be doing that.
 
The end result is I want to be able to deterministically encrypt and decrypt data between users.
 
thanks

dark.cton

unread,
Aug 22, 2013, 5:33:49 PM8/22/13
to sjcl-d...@googlegroups.com


On Thursday, August 22, 2013 11:24:49 PM UTC+2, Kevin McDowell wrote:
I have code that uses SJCL to encrypt and decrypt arrays of data.  It encrypts fine, but when it decrypts, I always get the error, "ccm: tag doesn't match". 
 
My code looks like this:
 
To encrypt:
          var p = "{\"iv\":\"9Xz/lNqbuATWz+H3viOAQA\",\"v\":1,\"iter\":1000,\"ks\":128,\"ts\":64,\"mode\":\"ccm\",\"adata\":\"\",\"cipher\":\"aes\",\"salt\":\"ItnNFEoD4vc\"}";
 
Why are you entering your options as a JSON-String and not as an options object?
Also be careful about giving an iv. An IV should not repeat itself!

          var encrypted = sjcl.encrypt(password,  rawData, p, rp);
          encrypted = encrypted.match(/"ct":"([^"]*)"/)[1];

          
To decrypt:
          var encodedData = test.value[i][j];
          var coded = "{\"iv\":\"9Xz/lNqbuATWz+H3viOAQA\",\"v\":1,\"iter\":1000,\"ks\":128,\"ts\":64,\"mode\":\"ccm\",\"adata\":\"\",\"cipher\":\"aes\",\"salt\":\"ItnNFEoD4vc\",\"ct\":\"" + encodedData + "\"}" 
          var decrypted = sjcl.decrypt(password, coded);
 
Are the parameters passed in for the 3rd argument for sjcl.encrypt ignored?
 
No they are not ignored but they are merged with the default ones. I am not sure what is happening when you input them as a JSON-String.

Kevin McDowell

unread,
Aug 22, 2013, 5:39:42 PM8/22/13
to sjcl-d...@googlegroups.com
 
No they are not ignored but they are merged with the default ones. I am not sure what is happening when you input them as a JSON-String.
 
I also tried passing the parameters as an array and that also returned the CCM error:
 
var coded = { adata:'', cipher:'aes', iter:256, mode:'ccm', ts:64, ks:256, iv:'9Xz/lNqbuATWz+H3viOAQA', salt:'ItnNFEoD4vc', ct:encodedData }; 

dark.cton

unread,
Aug 22, 2013, 5:59:06 PM8/22/13
to sjcl-d...@googlegroups.com
I want you to pass the parameters as an object in the encrypt step.
Also warning: do not reuse an iv again and again!
Another thing: you do not need to pass the parameters to the decryption step if encodedData is exactly what comes out of your encryption step.
Just pass the encodedData.

Regards,
Nils

Michael Hamburg

unread,
Aug 23, 2013, 12:59:03 AM8/23/13
to sjcl-d...@googlegroups.com
Hi Kevin,

The params object needs to be an object.  SJCL should probably check for that and complain at you when you pass a string, but instead it goes berserk (see what var encrypted actually gets before the .match).

Also, don't set the IV to a fixed value.  It must be different for every message, or else the cipher is completely insecure.

Cheers,
-- Mike

--
You received this message because you are subscribed to the Google Groups "SJCL discussion" group.
To unsubscribe from this group and stop receiving emails from it, send an email to sjcl-discuss...@googlegroups.com.
For more options, visit https://groups.google.com/groups/opt_out.

Kevin McDowell

unread,
Aug 23, 2013, 3:48:36 PM8/23/13
to sjcl-d...@googlegroups.com
I think I or my laptop screwed up as my previous response never showed up.
 
My scenario is this:
  1. User 1 has many small data sets (think a KB array of bytes).
  2. He encrypts them all with the same password using SJCL and stores them in the cloud.
  3. He separately communicates the password to User 2.
  4. User 2 later goes to the cloud, armed only with the password, and decrypts those data sets and uses them.
 
Is this scenario not possible with SJCL?  Shouldn't you be able to encrypt/decrypt with ONLY a password?
 
It's not feasible to store json strings for each small data set, as that will grow the data rather quickly.
 
thanks 

dark.cton

unread,
Aug 23, 2013, 4:39:45 PM8/23/13
to sjcl-d...@googlegroups.com


On Friday, August 23, 2013 9:48:36 PM UTC+2, Kevin McDowell wrote:
I think I or my laptop screwed up as my previous response never showed up.

I got some of your missing responses via mail but they did not show up here. Maybe google groups screwed up :)
 
 
My scenario is this:
  1. User 1 has many small data sets (think a KB array of bytes).
  2. He encrypts them all with the same password using SJCL and stores them in the cloud.
  3. He separately communicates the password to User 2.
  4. User 2 later goes to the cloud, armed only with the password, and decrypts those data sets and uses them.
Is this scenario not possible with SJCL?  Shouldn't you be able to encrypt/decrypt with ONLY a password?
 
 You can remove all data except the iv. For new data you should always use a new iv. Everything else is the same and as such can be removed in storage.

It's not feasible to store json strings for each small data set, as that will grow the data rather quickly.

You can also convert the iv and ct to binary data and store them like that.
On the other hand, if the small datasets are not changing often, you can encrypt them as one big dataset (with seperators) or if small parts change quickly, you could encrypt the initial big dataset once and then encrypt the changes and apply them dynamically.

As a first task I would do:
var data = sjcl.encrypt(pw, data[i][j])
data = sjcl.json.decode(data);
store(data.iv, data.ct);

data = store.get;
sjcl.json.encode(data); //only consists of iv and ct.
sjcl.decrypt(pw, data); // sjcl automatically adds default options here.
 
Regards,
Nils
Reply all
Reply to author
Forward
0 new messages