1

I have an issue with HTTP POST requests encrypting & decrypting.

I have an OS X Application written in Objective-C which sends encrypted (CocoaSecurity) HTTP POST request to server:

- (NSString *)secure
{
    NSData* key = [@"9eab87dc72b927c9" dataUsingEncoding:NSASCIIStringEncoding];
    NSData* iv = [@"d6f8f85911c4d8d1" dataUsingEncoding:NSASCIIStringEncoding];

    CocoaSecurityResult *result = [CocoaSecurity aesEncrypt:@"a" key:key iv:iv];

    return result.hexLower;    
}

and I am getting encryption

5219abd6c1439dc832ab512dae8cce80

Also I have a WEB Application written in PHP which decrypts sent request

protected function processEncrypt()
{
    if ($this->input) {
        $crypt = mcrypt_module_open($this->algorithm, '', $this->mode, $this->encryptIv);
        mcrypt_generic_init($crypt, $this->encryptKey, $this->encryptIv);
        $this->input = mcrypt_generic($crypt, $this->input);
        mcrypt_generic_deinit($crypt);
        mcrypt_module_close($crypt);

        if ($this->template == 'hex') {
            $this->input = bin2hex($this->input);
        } elseif ($this->template == 'base64') {
            $this->input = base64_encode($this->input);
        }
    }
}

The encrypted message, at the end of request handling, is totally different from the decrypted one.

I am getting encryption

10967675e5cf70878ee063a73f2a8394

Until now I have found out, that this might be a PKCS#7 padding issue (PHP mcrypt library has null padding). I have tried to remove padding by changing CocoaSecurity.m source and replacing kCCOptionPKCS7Padding value to 0. After this replacement, CocoaSecurity raises exception Encrypt Error!triggered by kCCAlignmentError...

Could anyone tell me, where is the problem?

Daumantas Versockas
  • 797
  • 1
  • 10
  • 29
  • Yes it is: `NSString+Security.h`. – Daumantas Versockas Aug 21 '15 at 11:38
  • 'algorithm' => 'rijndael-128', 'mode' => 'cbc', – Daumantas Versockas Aug 21 '15 at 12:11
  • For further help you need to supply example hex dumps of the key, iv, data in and data out just prior to and after the encryption operations. – zaph Aug 21 '15 at 12:33
  • Encrypting letter "a" I am getting with php `10967675e5cf70878ee063a73f2a8394`, and with Objective-C `82c4620a 24c3d673 c78e4f01 21ce6386 61fc07c0 17d85e2a a0961bb5 a281700c 370a432c 5ea9a32e aa5f3740 d9424e48 fea21542 35cf53e5 8b49fac1 7fd197b0 4785d317 386d80f6 400a8eb7 c3f02108 c7a12517 033c9b9f 42a54f9b 7e5d752a e27f8f31 ab63e82e a0b73670 29779cba ec28ef2f e422a753 61953cdf fb4f87de`, k_Encryption_KEY ="9EAB87DC72B927C9" k_Encryption_IV ="D6F8F85911C4D8D1" – Daumantas Versockas Aug 21 '15 at 12:37
  • The ObjC is obviously incorrect just based on the length. – zaph Aug 21 '15 at 12:41
  • But where is the problem? I am just using one function call: `CocoaSecurityResult *result = [CocoaSecurity aesEncrypt:self hexKey:k_Encryption_KEY hexIv:k_Encryption_IV];` – Daumantas Versockas Aug 21 '15 at 12:42
  • The data supplied is incorrect. `k_Encryption_KEY` and `k_Encryption_IV` are 8-bytes, they need to be 16-bytes. (16 hex ascii characters producs 8 bytes of binary data) With these keys CocoaSecurity throws the error: "Length of iv is wrong. Length of iv should be 16(128bits)" so this can't be what you are using. You need to provide a full minimal example. Fir testing it is best to supply a key and iv that are exactly one block in length (16-bytes for AES), this eliminates padding errors. It is also best to add additional information to the question, not in the comments. – zaph Aug 21 '15 at 13:23
  • This is full minima example. I have tried https://github.com/kelp404/CocoaSecurity/blob/master/CocoaSecurity/CocoaSecurity.m example (It is 16-bytes iv) and it throws exception: `Length of iv is wrong. Length of iv should be 16(128bits)`. Why? – Daumantas Versockas Aug 21 '15 at 13:34
  • You need to add a full minimal example of CocoaSecurity encryption complete with the key, iv, data in and data out and add that to the question. This because the values you provided for k_Encryption_KEY and k_Encryption_IV are an incorrect length and produces an exception, see above. The exception message is very clear that they are an incorrect length. CocoaSecurity explicitly checks that these have a correct length. The real question is do you want to get this to work? If so do the above. – zaph Aug 21 '15 at 13:54
  • 1. I suggest that inorder to reduce confusion you delete the comments related to the previous CocoaSecurity example. 2. Because CocoaSecurity used PKCS#7 padding and mcrypt used null padding the encrypted data will be different. You need to either change the mcrypt or CocoaSecurity usage to use the same padding method. Or if you **always** know a priori the data length on each side just grab that number of bytes. – zaph Aug 21 '15 at 14:16
  • Could you recommend a library with null padding for iOS (I need to provide key and iv)? – Daumantas Versockas Aug 21 '15 at 14:20
  • The encrypted output from CocoaSecurity is now correct for PKCS#7 padding since changing from hex to data for the key and iv. You can change the CocoaSecurity code by changing `kCCOptionPKCS7Padding` to 0 and and padding the data to a multiple of the block size (16-bytes) with 0 (0x00) bytes. But this is insecure and will not work if the data to be encrypted can ever have 0 (0x00) as the last byte. If you always know the length on both sides you can get by without padding but that is rarely a good idea. It is better to remove the PKCS#7 padding in php. – zaph Aug 21 '15 at 14:44
  • When I am replacing value `kCCOptionPKCS7Padding` to value `0` I am getting `Encrypt Error!`. How that could be? – Daumantas Versockas Aug 24 '15 at 05:49
  • Exception is triggered by `kCCAlignmentError`... – Daumantas Versockas Aug 24 '15 at 08:57
  • Without `kCCOptionPKCS7Padding` the input data length must be a multiple of the block size (16-bytes) because AES it is a block based encryption method. You will need to add padding to the data prior to calling the CCCrypt method. The best solution is to add PKCS#7 padding to the data on the mcrypt side. From CommonCryptor.h: `kCCAlignmentError` indicates that dataInLength was not properly aligned. This can only be returned for block ciphers, and then only when decrypting or when encrypting with block with padding disabled. – zaph Aug 24 '15 at 12:56

1 Answers1

0

Note that CocoaSecurity uses standard PKCS#7 padding (kCCOptionPKCS7Padding) but mcrypt uses non-standard/insecure null padding. You will need to remove the PKCS#7 padding in your php code. You can use the this code:

Add PKCS#7 padding (php):

 $pad = $block - (strlen($str) % $block);
 $str .= str_repeat(chr($pad), $pad);

Remove PKCS#7 padding (php):

$len = strlen($str);
$pad = ord($str[$len-1]);
$str = $strsubstr($str, 0, $len - $pad);

See this SO answer for detailed information.

Community
  • 1
  • 1
zaph
  • 111,848
  • 21
  • 189
  • 228
  • I am sending encrypted one letter "a" (padding shouldn't be applied), but the message is still undecriptable... – Daumantas Versockas Aug 21 '15 at 12:08
  • Padding is generally necessary because AES is a block algorithm and only handles block sized data with a block size of 16-bytes. A single byte must be extended to a block size in encryption and reduced on decryption. The only time padding is not required is if the data is exactly a multiple of the block size and that is known a priori to both sides. If padding is not supplied and the data is not a multiple of the block size the rest of the final block will be filled with undefined data. – zaph Aug 21 '15 at 12:30
  • Encrypting letter "a" I am getting with php `10967675e5cf70878ee063a73f2a8394`, and with Objective-C `82c4620a 24c3d673 c78e4f01 21ce6386 61fc07c0 17d85e2a a0961bb5 a281700c 370a432c 5ea9a32e aa5f3740 d9424e48 fea21542 35cf53e5 8b49fac1 7fd197b0 4785d317 386d80f6 400a8eb7 c3f02108 c7a12517 033c9b9f 42a54f9b 7e5d752a e27f8f31 ab63e82e a0b73670 29779cba ec28ef2f e422a753 61953cdf fb4f87de` – Daumantas Versockas Aug 21 '15 at 12:34