9

Encryption

The encryption is done with Stanford Javascript Crypto Library (SJCL). Below is a complete encryption example divided into two parts. The first is about password based key derivation with PBKDF2. In the second part the actual encryption happens with the derived key and an initialization vector (IV). Note that salt and IV is hard coded so that it is easier to provide a C# decryption solution.

// Key derivation…
var password = "password";
var salt = sjcl.codec.hex.toBits(
    "5f9bcef98873d06a" // Random generated with sjcl.random.randomWords(2, 0);
);                     // Hex encoded with sjcl.codec.hex.toBits(randomSalt);
var iterations = 1000;
var keySize = 128;
var encryptionKey = sjcl.misc.pbkdf2(password, salt, iterations, keySize);

// Encryption…
var blockCipher = new sjcl.cipher.aes(encryptionKey);
var plainText = sjcl.codec.utf8String.toBits("secret");
var iv = sjcl.codec.hex.toBits("8291ff107e798a29");
var adata = ""; // What is adata?
var tag = 64; // What is tag? I think it is authentication strength.
var cipherText = sjcl.mode.ccm.encrypt(blockCipher, plainText, iv, adata, tag);

The value of the encryptionKey variable:

  • SJCL bit array: [ -74545279, -553931361, -1590906567, 1562838103 ]
  • Hex encoded: fb8e8781defbad9fa12cb1395d270457
  • Base64 encoded: +46Hgd77rZ+hLLE5XScEVw==

The value of the iv variable:

  • SJCL bit array: [ -2104361200, 2121894441 ]
  • Hex encoded: 8291ff107e798a29
  • Base64 encoded: gpH/EH55iik=

The value of the cipherText variable:

  • SJCL bit array: [ 1789401157, -1485204800, -440319203, 17593459146752 ]
  • Hex encoded: 6aa81845a77992c0e5c1431d4be2
  • Base64 encoded: aqgYRad5ksDlwUMdS+I=

Question

The question is:

How can I decrypt the cipher text with Bouncy Castle?


Working decryption example after help from jbtule below

using Org.BouncyCastle.Crypto.Engines;
using Org.BouncyCastle.Crypto.Modes;
using Org.BouncyCastle.Crypto.Parameters;

namespace SjclHelpers {

    public static class Encryption {

        /// <summary>Decrypts the cipher text.</summary>
        /// <param name="cipherText">The cipher text.</pararesm>
        /// <param name="key">The encryption key.</param>
        /// <param name="initializationVector">The IV.</param>
        /// <returns>The decrypted text.</returns>
        public static byte[] Decrypt(this byte[] cipherText,
            byte[] key, byte[] initializationVector) {
            var keyParameter = new KeyParameter(key);
            const int macSize = 64;
            var nonce = initializationVector;
            var associatedText = new byte [] {};
            var ccmParameters = new CcmParameters(
                keyParameter,
                macSize,
                nonce,
                associatedText);
            var ccmMode = new CcmBlockCipher(new AesFastEngine());
            var forEncryption = false;
            ccmMode.Init(forEncryption, ccmParameters);
            var plainBytes =
                new byte[ccmMode.GetOutputSize(cipherText.Length)];
            var res = ccmMode.ProcessBytes(
                cipherText, 0, cipherText.Length, plainBytes, 0);
            ccmMode.DoFinal(plainBytes, res);
            return plainBytes;
        }}}

I get a System.ArgumentException. I think it is complaining about that one of the byte arrays is to short.

Boncy Castle is available at the NuGet site at this location: http://nuget.org/packages/BouncyCastle.


About

The AES/CCM decryption solution will be part of the SjclHelpers project at CodePlex and will be released as a NuGet package.

knut
  • 4,699
  • 4
  • 33
  • 43
  • How is the key retrieved? In my experience, if you aren't using a certificate, you may not be recovering the encryption key properly. – James Black May 01 '12 at 11:36
  • I decode an hex encoded key. The decoding is done like this: http://sjclhelpers.codeplex.com/SourceControl/changeset/view/12115#232154 (Test `ToBytes_ValidHex_CorrectBytes`). The decoding is implemented like this: http://sjclhelpers.codeplex.com/SourceControl/changeset/view/12115#232153 (The method `ToBytes(this string hex)`) – knut May 01 '12 at 11:41
  • You'll need to implement PBKDF2 in C# at least to get the same key. There's [an implementation in this old question](http://stackoverflow.com/questions/3210795/pbkdf2-in-bouncy-castle-c-sharp) if Bouncy Castle really doesn't have its own implementation, although the Java version at least seems to have a SecretKeyFactory class that'll do it. – Rup May 01 '12 at 12:24
  • I have implemented PBKDF2 (http://sjclhelpers.codeplex.com/SourceControl/changeset/view/12115#233554). In this case I don't need to use PBKDF2 because I have the key that has been derived from the password in the password based key derivation. See the encryption section above. The key in hex `6aa81845a77992c0e5c1431d4be2`. – knut May 01 '12 at 12:33
  • 1
    Umm, you say your question `6aa81845a77992c0e5c1431d4be2` is the cipher text not the key? – jbtule May 01 '12 at 15:11
  • Sorry. You are right. I see that now. Thanks! I have updated my question with the value of the derived encryption key. The encryption key in hex is `fb8e8781defbad9fa12cb1395d270457` not `6aa81845a77992c0e5c1431d4be2` which is the cipher text. – knut May 01 '12 at 15:58

2 Answers2

2

From what I can see:

  1. Nonce should be the IV.
  2. Generally you use AeadParameters instead of CcmParameters but that might still be okay, for sure don't wrap it with ParametersWithIV
  3. associateText is optional, because CCM can authenticate unencrypted data that is related to your encrypted data if you need it. You probably need an argument as it needs to be the same as sjcl adata and the method of transport could be anything.
  4. It is correct that tag and macSize are the same.
  5. DoFinal should be ccmMode.DoFinal(plainBytes, res);
  6. For security, after decryption, you should compare the last (macSize / 8) bytes of the cipherText to ccmMode.GetMac() to check the authentication.
  7. var plainBytes = new byte[ccmMode.GetOutputSize(cipherText.Length)]
jbtule
  • 31,383
  • 12
  • 95
  • 128
  • I also have a [example of AES-GCM in Bouncy Castle](http://stackoverflow.com/a/10366194/637783) which is similar to AES-CCM. I use the associatedtext to send info about the salt and iterations when using PBKDF2. – jbtule May 01 '12 at 15:37
  • Oh, and you should set the plainBytes size appropriately, I updated the answer. – jbtule May 01 '12 at 17:09
  • Thanks! Updated decryption example in question. – knut May 01 '12 at 18:07
  • @knut Just remember in your actual library, checking the MAC/Tag is important after decryption and it should be flexible so that the library consumers can use pass in some associatedData if they want since they can do it on the javascript side. – jbtule May 01 '12 at 18:16
1

You cannot decrypt sjcl JSON with Bouncy Castle. Because SJCL's pre-computed table is different from Bouncy Castle's one. I made own library. If you still looking for decrypting solution, have a try. https://github.com/mebius1080p/SJCLDecryptor