I'm using Apple's SecKeyWrapper class from the CryptoExercise sample code in the Apple docs to do some symmetric encryption with AES128. For some reason, when I encrypt 1-15 characters or 17 characters, it encrypts and decrypts correctly. With 16 characters, I can encrypt, but on decrypt it throws an exception after the CCCryptorFinal call with ccStatus == -4304, which indicates a decode error. (Go figure.)
I understand that AES128 uses 16 bytes per encrypted block, so I get the impression that the error has something to do with the plaintext length falling on the block boundary. Has anyone run into this issue using CommonCryptor or SecKeyWrapper?
The following lines...
// We don't want to toss padding on if we don't need to
if (*pkcs7 != kCCOptionECBMode) {
if ((plainTextBufferSize % kChosenCipherBlockSize) == 0) {
*pkcs7 = 0x0000;
} else {
*pkcs7 = kCCOptionPKCS7Padding;
}
}
... are the culprits of my issue. To solve it, I simply had to comment them out.
As far as I can tell, the encryption process was not padding on the encryption side, but was then still expecting padding on the decryption side, causing the decryption process to fail (which is generally what I was experiencing).
Always using kCCOptionPKCS7Padding to encrypt/decrypt is working for me so far, for strings that satisfy length % 16 == 0 and those that don't. And, again, this is a modification to the SecKeyWrapper class of the CryptoExercise example code. Not sure how this impacts those of you using CommonCrypto with home-rolled wrappers.
I too have encountered this issue using the CommonCrypto class but for ANY string with a length that was a multiple of 16.
My solution is a total hack since I have not yet found a real solution to the problem.
I pad my string with a space at the end if it is a multiple of 16. It works for my particular scenario since the extra space on the data does not affect the receipt of the data on the other side but I doubt it would work for anyone else's scenario.
Hopefully somebody smarter can point us in the right direction to a real solution.
Related
I'm running a security code analysis with Kiuwan on one of my Swift libs and I got one issue marked as hight vulnerability that says exactly what the title read and it's point me out this portion of my code:
53 public let data: Data
54 public var base64String: String {
55 return data.base64EncodedString()
56 }
The line 55 to be precise, witch is the Swift built in base64 string encoder from Data
Any Idea of what can I do in order to fix that vulnerability ?
If you are NOT doing encryption (wanting to perserve the confidentiality and integrity of data) then you have a false positive here. Static code analyser tools meant for security scanning are generating false positives in huge amounts. You need to dig through, understand the context and decide whether it is a bug or not yourself.
If you are doing encryption here, then it is obviously wrong.
I am using C_Decrypt with the CKM_AES_CBC_PAD mechanism. I know that my ciphertext which is 272 bytes long should actually decrypt to 256 bytes, which means a full block of padding was added.
I know that according to the standard when invoking C_Decrypt with a NULL output buffer the function may return an output length which is somewhat longer than the actual required length, in particular when padding is used this is understandable, as the function can't know how many padding bytes are in the final block without carrying out the actual decryption.
So the question is whether if I know that I should get exactly 256 bytes back, such as in the scenario I explained above, does it make sense that I am still getting a CKR_BUFFER_TOO_SMALL error as a result, despite passing a 256 bytes buffer? (To make it clear: I am indicating that this is the length of the output buffer in the appropriate output buffer length parameter, see the parameters of C_Decrypt to observe what I mean)
I am encountering this behavior with a Safenet Luna device and am not sure what to make of it. Is it my code's fault for not querying for the length first by passing NULL in the output buffer, or is this a bug on the HSM/PKCS11 library side?
One more thing I should perhaps mention is that when I provide a 272 (256+16) bytes output buffer, the call succeeds and I am noticing that I am getting back my expected plaintext, but also the padding block which means 16 final bytes with the value 0x10. However, the output length is updated correctly to 256, not 272 - this also proves that I am not using CKM_AES_CBC instead of CKM_AES_CBC_PAD accidentally, which I suspected for a moment as well :)
I have used CKM.AES_CBC_PAD padding mechanism with C_Decrypt in past. You have to make 2 calls to C_Decrypt (1st ==> To get the size of the plain text, 2nd ==> Actual decryption). see the documentation here which talks about determining the length of the buffer needed to hold the plain-text.
Below is the step-by-step code to show the behavior of decryption:
//Defining the decryption mechanism
CK_MECHANISM mechanism = new CK_MECHANISM(CKM.AES_CBC_PAD);
//Initialize to zero -> variable to hold size of plain text
LongRef lRefDec = new LongRef();
// Get ready to decrypt
CryptokiEx.C_DecryptInit(session_1, mechanism, key_handleId_in_hsm);
// Get the size of the plain text -> 1st call to decrypt
CryptokiEx.C_Decrypt(session_1, your_cipher, your_cipher.length, null, lRefDec);
// Allocate space to the buffer to store plain text.
byte[] clearText = new byte[(int)lRefDec.value];
// Actual decryption -> 2nd call to decrypt
CryptokiEx.C_Decrypt(session_1, eFileCipher, eFileCipher.length, eFileInClear,lRefDec);
Sometimes, decryption fails because your input encryption data was misleading (however, encryption is successful but corresponding decryption will fail) the decryption algorithm. So it is important not to send raw bytes directly to the encryption algorithm; rather encoding the input data with UTF-8/16 schema's preserves the data from getting misunderstood as network control bytes.
So I am trying to decrypt a connection over SSH using pycryptodome.
I have the key and the IV extracted from memory (I am working inside a virtual environment), which are 100% correct, which were used for encrypting the data.
Now I want to decrypt the stuff afterwards.
My code looks as follows:
key="1A0A3EBF96277C6109632C5D96AC5AF890693AC829552F33769D6B1A4275EAE2"
iv="EB6444718D73887B1DF8E1D5E6C3ECFC"
key_hex=binascii_a2b_hex(key)
iv_hex=binascii_a2b_hex(iv)
ctr = Counter.new(128, prefix=iv_hex, initial_value = 0)
aes = AES.new(key, AES.MODE_CTR, counter = ctr)
decrypted = aes.decrypt(binascii.a2b_hex(cipher).rstrip())
print(decrypted)
The problem is now that the counter is too big (32 bytes) for the blocksize which is 16 byte in AES. However, I found out that you need the IV as the prefix in your counter if you want to decrypt AES-CTR plus the initial_value set to 0.
Therefore I already have 16 Byte with only the Prefix. When I know want to set the first value in the counter object to 0 it does not work.
Is it even possible to decrypt AES-CTR with a 16 Byte IV using pycryptodome? Or maybe someone of you sees my error.
Any help would be much appreciated.
Thanks in advance!
Edit: Thanks to SquareRootOfTwentyThree I solved the pycryptodome problem. Unfortunately the decryption is still not working so I opened a new Thread. openssh/opensshportable, which key should I extract from memory?
As per Chapter 4 in RFC4344, SSH uses SDCTR mode (stateful-decryption CTR mode), which means that the counter block is a 128-bit counter, starting with a value represented in the IV as encoded in network order, and with no fixed parts (unlike NIST CTR mode).
With PyCryptodome, you do that with:
aes = AES.new(key_hex, AES.MODE_CTR, initial_value=iv_hex, nonce=b'')
Note: there seems to be an error in your code - you initialize the cipher with key (hexadecimal string) and not key_hex (bytes).
I found a pretty annoying and serious problem in iTextSharp's zlib implementation. Very hard to reproduce because it depends on the actual data going into the PDF but in some circumstances, the following exception occurs:
System.IndexOutOfRangeException: Index was outside the bounds of the array.
at System.util.zlib.Tree.d_code(Int32 dist)
at System.util.zlib.Deflate.compress_block(Int16[] ltree, Int16[] dtree)
In System.util.zlib.Tree.cs, there is obviously no range check, only an assumption of things never going wrong. Adding the following (byte) cast seems to be a solution:
internal static int d_code(int dist){
return ((dist) < 256 ? _dist_code[dist] : _dist_code[256+(byte)((dist)>>7)]);
}
I have seen this thread, and the encryption techniques mentioned there is working well. But not in all cases.
Requirement:
Simple, take one image, encrypt it, and store the encrypted data. Later, get the encrypted data, decrypt it, recreate the original image and show.
What I have done
From the above mentioned thread, I found NSData additions for AES 256 encryption. I tried to use it but with partial success. This is the code
//encryption
NSData *srcData = UIImageJPEGRepresentation(srcImage, 1.0);
NSLog(#"srcData length : %d",[srcData length]);
NSData *encryptedData = [srcData AES256EncryptWithKey:KEY];
NSLog(#"encrypted data length : %d",[encryptedData length]);
........
//later..
//decryption
decryptedImage = [UIImage imageWithData:[encryptedData AES256DecryptWithKey:KEY]];
imageView.image = decryptedImage;
What is happening
For a small image, say image with resolution 48*48, this code is working successfully. But when I run the code in an image with higher resolutions, say 256 * 256, the method AES256EncryptWithKey failing with error kCCBufferTooSmall (-4301).
Questions
Does AES 256 impose any limit on the size (in bytes) of the payload
to be encrypted?
If the answer to first question is YES, then what kind of
encryption algorithm to use in iphone, to encrypt image (probably
big ones)?
If the answer to the first question is NO, then why this error?
No, not really. Some hash functions do have a maximum, but that's more in the order of 2^64, so generally you don't have to worry.
N/A
It has probably something to do with the dataWithBytesNoCopy in combination with the malloc call, but it is hard to find out without actually running the code.
Note that that wrapper is pretty braindead, as it does require encrypting all at once, without using CCCryptorUpdate. It does not use an IV which jeopardizes security. It handles the keys as strings. Finally, it creates too big a buffer size for decryption. You are better off creating your own using a more reliable source.