Take the 2-minute tour ×

According to this article http://blog.gdssecurity.com/labs/2013/3/5/retrieving-crypto-keys-via-ios-runtime-hooking.html

There is "bad practices in Apple’s sample code for the doCipher:key:context:padding method http://developer.apple.com/library/ios/#samplecode/CryptoExercise/Listings/Classes_SecKeyWrapper_m.html. The following code snippet shows that it will use a static IV of 16 bytes of 0x0’s.

 // Initialization vector; dummy in this case 0’s.

uint8_t iv[kChosenCipherBlockSize];

memset((void *) iv, 0x0, (size_t) sizeof(iv));

Why is it really bad in layman's term and how to fix it ?

What I only understand is that it is possible to hook that code to intercept the symetric key. But I don't understand why and how to prevent this.

share|improve this question
Could you quickly summarize here what the blog says about the code? –  Josh Caswell May 18 '13 at 18:59
Well I'm no expert at all but I updated : What I only understand is that it is possible to hook that code to intercept the symetric key. But I don't understand why and how to prevent this. –  user310291 May 18 '13 at 19:01
That's fine. It's just in the interest of making this question continue to be useful should the blog post disappear for some reason. Thanks! –  Josh Caswell May 18 '13 at 19:03
add comment

2 Answers

up vote 4 down vote accepted

The code outlined in that post is insecure because it does not follow the rule about Initialization Vectors being random values. Notice that the engineer who wrote it commented:

//... dummy in this case 0’s.

True initialization vectors of a fixed size (or IVs, as the blog calls them) would never allocate a buffer to be passed to a crypto function with the same value over and over, they would instead randomize the data contained by the buffer each time so that its location could not be inferred by looking at the sample code provided -as the author did. Just cut out the call to memset(), and that block of memory will be filled with "junk" by the runtime. If you want to get technical, write your own version of memset() that generates pseudo-random data to overwrite the memory of that local.

share|improve this answer
This is the "how", but not the "why". The "why" is that if two messages are sent with the same key and initialization vector, a cryptanalyst can analyze those two enciphered messages together to discover things about the deciphered versions. Exactly how much he can discover depends on the type of cipher and the mode it's used in; see this former Stack Overflow post for details. –  Brent Royal-Gordon May 18 '13 at 21:58
@BrentRoyal-Gordon the "deciphered versions" are normally referred to as the "plain text", the key should stay safe though. –  owlstead May 18 '13 at 22:55
Just cutting out the call to memset() is extremely bad advice. That indeed means that the IV can contain unpredictable data, but that does not mean that it contains random data in the cryptographic sense. "pseudo-random data" (which is normally seeded in some kind of way) should be replaced by secure random data. The devil is in the details... –  owlstead May 18 '13 at 22:58
@owlstead I understand that just relying on runtime feaures is dangerous ('s why I suggested a rewrite of memset()). And the comment about pseudo-random generators can be generalized to seed algorithms or even just to a couple calls to some kind of ...rand-and-friends-esque function in a loop. While I see the need for nuance (occasionally), there's no use writing him a research paper! –  CodaFi May 18 '13 at 23:47
On the other hand, simply pointing to SecRandomCopyBytes may be more useful, and prefixing the IV to the ciphertext may be another. Random numbers are not just nuances for correct execution of crypto. –  owlstead May 18 '13 at 23:53
show 5 more comments

In Classes_SecKeyWrapper.m we see that the initialization vector (IV) is used in a call to CCCryptorCreate, which defaults to use cipher-block chaining (CBC) mode (as documented in CommonCryptor.h).

CBC mode XORs each block with the next before encrypting and ensures that two identical blocks don't produce the same result. Because the first block has no previous block to be XORed with, you are required to made up a block called “initialization vector”. This randomizes the output of the first block and lowers the chance of a replay attack or a chosen-ciphertext attack.

In CBC mode, the initialization vector should be random and unique for each call to CCCryptorCreate, and should be used by the encryptor and the decryptor code (so you have to send it along the message to whoever wants to decrypt the result).

The Apple sample code is commented with dummy in this case 0's. A dummy is a substitute for the real thing, so I believe the original writer was aware of the issue and simply chose to write a simplified example on purpose.

share|improve this answer
Thanks for this remark about dummy thing : I'm happy Apple's employee should know better than at first glance :) –  user310291 May 20 '13 at 10:24
add comment

Your Answer


