I have a string that has been encrypted using Java
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
cipher.init(Cipher.ENCRYPT_MODE, key);
return cipher.doFinal(text.getBytes());
(Note that in Java, PKCS5Padding is actually PKCS7Padding when using AES link)
And my decryption internal code is:
CCCryptorStatus cryptStatus = CCCrypt(kCCDecrypt,
kCCAlgorithmAES128,
0,
key.bytes,
kCCBlockSizeAES128,
iv.bytes,
[encrypted bytes],
dataLength,
buffer,
bufferSize,
&numBytesEncrypted);
called like:
let decryptedData = decryptor.AES128DecryptWithKeyString(key, encryptedString: encodedString) //this does the CCCrypt stuff
let string:NSString = NSString(data: decryptedData, encoding: NSUTF8StringEncoding) ?? ""
let data = NSData(base64EncodedString: string as String, options: NSDataBase64DecodingOptions.IgnoreUnknownCharacters)
So even though it was encrypted using PKCS5Padding, my decryption works fine despite not giving a padding option. Additionally, if I change the 0
option to kCCOptionPKCS7Padding
it also works to decrypt.
Is this the expected behavior? Is the padding option only relevant for kCCEncrypt and not kCCDecrypt?
Additionally, if we change the Java encryption to
Cipher cipher = Cipher.getInstance("AES/CBC/NoPadding");
and pad the payload manually with zero bytes, then it still decrypts properly regardless of whether I use 0
as an option or kCCOptionPKCS7Padding
When you say that the padding does not affect decryption are you looking at the output in a hex dump?
The padding will be trailing characters in the range of 0x01
to 0x10
which are non printing ASCII characters so it may seem the same when printing a string that has been encrypted with PKCS#7 padding but decrypted with a padding option.
Add sample output both ways as a hex dump to the question and you should see what is really happening.
The return status does not indicate correct decryption or invalid padding, only gross calling errors.
Example:
let keyData = Array("12345678901234567890123456789012".utf8)
let messageData = Array("Don´t try".utf8)
let encrypted = testCrypt(data:messageData, keyData:keyData, operation:kCCEncrypt, options:UInt32(kCCOptionPKCS7Padding))!
print("encrypted: \(encrypted)")
let decryptedPKCS7 = testCrypt(data:encrypted, keyData:keyData, operation:kCCDecrypt, options:UInt32(kCCOptionPKCS7Padding))!
print("decrypted PKCS7: \(decryptedPKCS7)")
let decryptedNone = testCrypt(data:encrypted, keyData:keyData, operation:kCCDecrypt, options:UInt32(0))!
print("decrypted None: \(decryptedNone)")
Output:
encrypted: [136, 95, 194, 76, 137, 107, 196, 39, 245, 108, 106, 84, 139, 49, 14, 139] decrypted PKCS7: [68, 111, 110, 194, 180, 116, 32, 116, 114, 121] decrypted None: [68, 111, 110, 194, 180, 116, 32, 116, 114, 121, 6, 6, 6, 6, 6, 6]
The trailling six 0x06
bytes are the unremoved padding.