2

I'm trying to implement secure encryption of the files to be sent over insecure channel or stored in an insecure place. I use bouncy castle framework, my code is written in . I decided to use -256 (to be more specific - Rinjael with 256 bit block size, here is why). And it seems like I can use Rinjael with any (128|160|192|256) block length.

I cannot understand the whole process overview correctly. Here is one of good answers, in this question there is some useful code specific to bouncy castle. But both leaving some questions unanswered for me (questions below).

So this is how I understand the workflow:

  1. For creating a block cipher instance I have to get an instance of padded block cipher with some output feedback:

    // create an instance of the engine
    val engine = new RijndaelEngine(bitLength)
    // wrap engine with some feedback-blocking cipher mode engine
    val ofb = new OFBBlockCipher(engine , bitLength)
    // wrap this with some padded-blocking cipher mode
    val cipher = new PaddedBufferedBlockCipher(ofb, new PKCS7Padding())
    
  2. Now I have to run init() on the cipher engine

    2.1. first generate a key, to do this the best solution suggested here was to use Scrypt to derive a secret from password instead of using PBKDF2-HMAC-xxx. In russian wikipedia article on Scrypt it is said that the recommended parameters for Scrypt are as follows: N = 16384, r = 8, p = 1 So I'we wrirtten this code to generate the password:

    SCrypt.generate(password.getBytes(encoding), salt, 16384, 8, 1, bitLength / 8)
    

    2.2. This leads to that I need a salt. Salt should be an array of random bytes. Most answers here use 8 bytes. So I do

    // helper method to get a bunch of random bytes
    def getRandomBytes(size: Int) = {
      val bytes = Array.ofDim[Byte](size)
      val rnd = new SecureRandom()
      rnd.nextBytes(bytes)
      bytes
    }
    // generate salt
    val salt = getRandomBytes(8)
    

    2.3. For cipher to initialize we need an initialization vector (please take a look at my question (2) below).

    val iv = getRandomBytes(bitLength / 8)
    

    2.4. Now we are ready to initialize the cipher.

    cipher.init(mode, params(password, salt, iv, bitLength))
    

Questions:

  1. What should be the size of salt? Why do most respondents here use 8 bytes, not more?
  2. What should be the size of IV? Is it correct that it should be the same size as cipher block size? Is it preferred to be fetched from cipher like here: cipher.getParameters().getParameterSpec(IvParameterSpec.class).getIV(); or to be just random as i did?
  3. Is it correct that I need both the salt and IV or I can use just one of these? For example use random IV as a salt.
  4. And the main question: I have to pass salt and IV to the other side or else it would be not possible to decrypt the message. I need to somehow pass both over unencrypted channel. Is it secure to just add both before an encrypted message (as a header)?

Thanks in advance!

Community
  • 1
  • 1
Oleg Stepura
  • 95
  • 2
  • 11

2 Answers2

2
  1. I would go for 16 bytes salt length as suggested
  2. IV should be size of block size of cipher and should be random
  3. Yes you need both salt and IV because salt is used to generate key from password and IV is used to initialize block cipher
  4. Salt and IV are designed to be public. You can send them or store unencrypted, but you do not use any authentication mechanism so anyone can change IV or Salt during transport and you would not be able to detect it and decryption will get you something different. To prevent that you should use some AEAD mode and include IV and salt in authentication.
Community
  • 1
  • 1
Maciej S
  • 586
  • 4
  • 8
  • The 256 in AES means key length, AES always have 128 bit block size, I do not see any reason to go for 256 block size of Rijndael. The link you posted also states that. – Maciej S Oct 11 '13 at 13:27
  • Yes, didn't think of modification of the salt or IV. But modifying it should lead to unencryptable (malformed) message, shouldn't it? – Oleg Stepura Oct 11 '13 at 16:30
  • isn't 256-bit block sized Rijndael more secure than 128-bit block sized Rijndael? – Oleg Stepura Oct 11 '13 at 16:57
  • Yes modiefied salt or IV will lead to malformed message. Block size have nothing to do with security. Key size does. – Maciej S Oct 12 '13 at 16:41
  • As you already pointed out IV size should be of a block size meaning the less is block size the less IV size is. But smaller IV size may lead to some weakness when it's too small to interfere when taken from random. Does this make any sense? – Oleg Stepura Oct 14 '13 at 08:08
  • Block size and IV will affect total byte count you can encrypt without loosing security. – Maciej S Oct 14 '13 at 14:32
0

Is it secure? Sure, they will still need to guess the passphrase. Is it as secure? No, because you're giving the attacker information that they need to simplify the decryption process. If the only way that you can get the salt/password to the other side is via an unencrypted channel then something is better than nothing I suppose, but why can't you exchange this information using PKI/SSL?

FuriousGeorge
  • 4,561
  • 5
  • 29
  • 52
  • Let's assume I will store the encrypted file in some public place. The only thing that user has to enter is the password to decrypt the file. Take as an example 7zip: it allows you to encrypt your files. And only thing that user has to enter is password. – Oleg Stepura Oct 10 '13 at 16:39
  • 1
    The salt is there mainly to prevent rainbow table attacks. Providing the salt in the file would only be a problem if you believe that the attacker has a table for every possible salt combination. In your scenario, as long as you pick a difficult password you should be fine. Also, you might want to ask your question on http://crypto.stackexchange.com/ which is more specialized towards this. – FuriousGeorge Oct 10 '13 at 16:58