Encrypt with openssl and decrypt on iPhone with AES 128, ecb mode

Update: solution found. I will update this question soon with the actual working code and team.


The client encrypts the server-side file using C ++, and I need to decrypt it in the iPhone application.

My client can glue and decrypt on their side, and I can also on the iPhone, but we can not decrypt the file encrypted by each other. I saw a lot of related questions on SO, but no one could help me find an implementation that works the same on both sides.

I want to derive some approximate values ​​that we will take as a general implementation.

I tried to hide the file using openssl and decrypt it using cocoa, but could not.

Here is what I use for encryption:

echo "123456789ABCDEFG" | openssl enc -aes-128-ecb -nosalt -K "41414141414141414141414141414141" -iv 0 > hello.txt.bin

Adding the -p option to the openssl call shows that the expected key and iv are used:

 key=41414141414141414141414141414141 iv =00000000000000000000000000000000 

And for cocoa decryption (in NSData category):

 - (NSData *)AESDecryptWithKey:(NSString *)key { char keyPtr[kCCKeySizeAES128+1]; // room for terminator (unused) bzero(keyPtr, sizeof(keyPtr)); // fill with zeroes (for padding) // fetch key data [key getCString:keyPtr maxLength:sizeof(keyPtr) encoding:NSUTF8StringEncoding]; NSUInteger dataLength = [self length]; //See the doc: For block ciphers, the output size will always be less than or //equal to the input size plus the size of one block. //That why we need to add the size of one block here size_t bufferSize = dataLength + kCCBlockSizeAES128; void *buffer = malloc(bufferSize); size_t numBytesEncrypted = 0; char iv[32]; for (int i = 0; i < 32; i++) { iv[i] = 0; } CCCryptorStatus cryptStatus = CCCrypt(kCCDecrypt, kCCAlgorithmAES128, kCCOptionECBMode + kCCOptionPKCS7Padding, keyPtr, kCCKeySizeAES128, iv, //"00000000000000000000000000000000" /* initialization vector (optional) */, [self bytes], dataLength, /* input */ buffer, bufferSize, /* output */ &numBytesEncrypted); if (cryptStatus == kCCSuccess) { //the returned NSData takes ownership of the buffer and will free it on deallocation return [NSData dataWithBytesNoCopy:buffer length:numBytesEncrypted]; } free(buffer); //free the buffer; return nil; } 

called as follows:

 - (void)testBinaryFileDecryption { NSString *databasePath = [[NSBundle mainBundle] pathForResource:@"hello" ofType:@"txt.bin"]; NSData *data = [NSData dataWithContentsOfFile:databasePath]; NSAssert(nil != data, @"Encrypted data, freshly loaded from file should not be nil"); NSData *plain = [data AESDecryptWithKey:@"AAAAAAAAAAAAAAAA"]; NSAssert(nil != plain, @"Decrypted plain data should not be nil"); NSLog(@"Result: '%@'", [[NSString alloc] initWithData:plain encoding:NSASCIIStringEncoding]); } 

Logs of results: Result: '4¨µ¢Ä½Pk£N

Which option did I forget? Is NSData encoding a return of something else than NSASCIIStringEncoding?

+3
source share
2 answers

I don’t know anything about iPhone development, but looking at this code, it seems you are trying to use ascii-of-hex encoding for the actual key to decrypt the package. OpenSSL enc requires hexadecimal encoding because it converts the hexadecimal code to bytes. Your actual key is more like this when it is converted directly to ascii.

 ["\037", " ", "!", "\"", "#", "$", "%", "&", "'", "\036", "\037", " ", "!", "\"", "#", "$"] 

(Everything can be dumb. If you were to encode the string you use for decryption into the same format that OpenSSL accepts, the key will be 3331333233333334333533363337333833393330333133323333333433353336 )

Try using key specification 41414141414141414141414141414141 for OpenSSL and use AAAAAAAAAAAAAAAA in your iPhone code.

In addition, I highly recommend that your initial tests be done with data that is exactly N * 16 bytes in size. OpenSSL enc uses PKCS # 5 padding (if you don't use -nopad ), and your iPhone code uses the PKCS # 7 add-on. On a quick look at RFCs, they seem to be the same fill mechanism, but I could be wrong.

And I know that you are just trying to do it here, but in real production code, please do not use ECB mode .

+2
source

I use Crypt :: OpenSSL :: AES to encrypt files that are decrypted in my iOS application, which is decrypted using CommonCryptor.

  cryptStatus = CCCrypt(kCCDecrypt, kCCAlgorithmAES128, 0, keyPtr, kCCKeySizeAES256, IVECTOR /* initialization vector (optional) -- was NULL*/, [self bytes], dataLength, /* input */ buffer, bufferSize, /* output */ &numBytesDecrypted); 

I use bzero to initialize IVECTOR.

 bzero(keyPtr, sizeof(keyPtr)); // fill with zeroes (for padding) 

To encrypt under OpenSSL in perl, I do this:

 my $cipher = Crypt::CBC->new( -key => $key, -literal_key => 1, -header => 'none', -iv => '0000000000000000', -cipher => 'Crypt::OpenSSL::AES' ); 

OpenSSL seems to accept "0000000000000000" IV as the same thing as ASCII 0 (null) characters. It seems plausible in retrospect, but it takes a lot of hair pulling because every crypto malfunction looks like any other crypto malfunction: garbage collection.

+2
source

Source: https://habr.com/ru/post/910236/


All Articles