My question is about this question:
Is your product designed to use cryptography or does it contain or incorporate cryptography?
I don't know what to answer because my app is using the commoncrypto framework and md5 encryption. What should I answer?
Codes used in App:
(NSString *) md5:(NSString *) input
{
const char *cStr = [input UTF8String];
unsigned char digest[16];
CC_MD5( cStr, strlen(cStr), digest ); // This is the md5 call
NSMutableString *output = [NSMutableString stringWithCapacity:CC_MD5_DIGEST_LENGTH * 2];
for(int i = 0; i < CC_MD5_DIGEST_LENGTH; i++)
[output appendFormat:#"%02x", digest[i]];
return output;
}
md5 is a hash function and hash functions are one-way and are not encryption.
If all you are using is a hash function the answer is No you are not using encryption.
If you are using AES, DES of other encryption, that is two-way crypto functions then the answer is YES.
Merely adding the CommonCrypto framework makes no difference, it is the usage of encryption that counts.
The only concern is any encryption in the app, there is no concern with anything done on a related server.
iTunes Connect does not care server-side implementation.
If you use MD5 or any other encryption mechanism in server side (but not in App side), you should choose No for the answer.
Related
We need to encrypt a request using AES128 in Android and IOS and then send that encrypted message in the backend server written in Java.
Our Android encryption code is like below:
Cipher cipher = Cipher.getInstance("AES/CBC/NoPadding");
cipher.init(Cipher.ENCRYPT_MODE, keyspec, ivspec);
where keyspec and ivspec is random bytes generated.
In Objective-C, this is how we do the encryption.
NSString* iv = #"a12bc1256b4de9a0";
NSData* ivData = [iv dataUsingEncoding:NSUTF8StringEncoding];
NSMutableData* cipherData = [NSMutableData dataWithLength:data.length+kCCBlockSizeAES128];
CCCryptorStatus result = CCCrypt(kCCEncrypt, kCCAlgorithmAES, kCCOptionPKCS7Padding, keyData.bytes, keyData.length, ivData.bytes, data.bytes, data.length, cipherData.mutableBytes, cipherData
.length, &outLength);
The problem with this is that when we compare the encrypted byte of thee Java program and Objective-C, they are not the same. I understand that the CCOption parameter in Objective-C should be CBC but that is not in the enum list of the CommonCrypto library. When we set it 0, the encrypted byte only return a series of zeros.
Please suggest other alternatives on how to do the AES 128 encryption in Objective-C using AES/CBC/NOPadding Algorithm.
You've requested padding: kCCOptionPKCS7Padding. That's not the same thing as Java's NoPadding. Remove the padding option. (You can use 0 to mean "no options.")
It's also unclear whether every other part of your encryption it the same. You didn't include the key generation or IV in the Java code.
(Note that if you get the exact same bytes out of an encryption algorithm for the same message, then you're using the encryption algorithm in an insecure way. Secure encryption constructions will generate a different cipher text for every encryption. I understand that your server may be using this kind of insecure approach; it's a very common mistake. But it is insecure.)
I'm studying c socket programming lately,so I write an example for practice of Client–server model. I use structure as message data to send to server, server processes the data. when i run in the IOS simulator, it's right, but in the device it's wrong, I find that the structure data which the server receives from the devices client is different from the client message data! I'm sorry my English is very bad.
my structure code is:
typedef struct Message
{
char msg[4000];
char name[256];
bool isBroadcast;
bool islogin;
USER userInfo;
}__attribute__((packed)) MessageType;
user code is :
typedef struct user
{
int id_number;
char name[256];
char password[20];
char *p_chatlog;
struct sockaddr user_addr;
int sock;
} __attribute__((packed)) USER;
send code is :
MessageType *loginMsg = (MessageType *)malloc(sizeof(MessageType));
bzero(loginMsg, sizeof(MessageType));
loginMsg->islogin = true;
const char *name_str = [userName.text UTF8String];
memcpy(&(loginMsg->userInfo.name), name_str, strlen(name_str));
const char *password_str = [password.text UTF8String];
memcpy(&(loginMsg->userInfo.password), password_str, strlen(password_str));
write(m_sock, loginMsg, sizeof(MessageType));
free(loginMsg);
server receive code use read() function, then make the receive chars transform structure type.
I would suggest that you make sure you send the data in network byte order; use the htonl, htons and ntohl, ntohs system functions. Different devices may well be a different endianness. Also, you probably shouldn't just send a struct over the network, even in network byte order, you would be better devising a simple protocol to send the data you require - it's more maintainable and flexible. You also can't guarantee your write has sent all of the data you requested, you should check the return results of both your read and write to ensure you have the amount you expect.
Incidentally, it is recommended to avoid the POSIX networking library for iOS and use the native implementation where possible.
I have implemented publickey privatekey RSA encryption in iOS application based on the examples provided on the Apple Developer site.
It works perfectly if I encrypt and return the uint8_t cipherBuffer, and then decrypt from the uint8_t cipherBuffer. However I need to store the encrypted data to an .xcdata model as NSData.
The problem I'm having is reliably converting the uint8_t cipherBuffer to NSData and/or converting the NSData back to uint8_t when it's time to decrypt. The decrypted data appears to be truncated.
This is how I'm converting the uint8_t encrypted buffer to NSData:
return [NSData dataWithBytesNoCopy:cipherBuffer length:BUFFER_SIZE];
This is how I'm converting the encrypted NSData back to a uint8_t buffer when it is time to decrypt it:
uint8_t *cipherBuffer = (uint8_t*)[cipherText bytes];
Thanks jgh and Jody;
I changed the encryption method to "malloc" the buffer and tried several approaches to write the bytes to NSData, wound up with:
return [NSData dataWithBytes:(const void *)cipherBuffer length:CIPHER_BUFFER_SIZE];
What finally fixed the issue was changing the way I was creating the uint8_t in the decryption method:
const uint8_t *cipherBuffer = (const uint8_t*)[data bytes];
Without seeing how you're creating cipherBuffer, it's difficult to say exactly why it's not working. However, from the documentation on dataWithBytesNoCopy:
The returned object takes ownership of the bytes pointer and frees it on deallocation. Therefore, bytes must point to a memory block allocated with malloc.
If you're just declaring cipherBuffer as
uint8_t cipherBuffer[BUFFER_SIZE];
it may explain your problems. Instead, use malloc:
uint8_t* cipherBuffer = malloc(BUFFER_SIZE);
It sounds like you are giving it a raw pointer, then re-using that pointer.
dataWithBytesNoCopy: wants to keep the pointer you give it. In fact, you must give it a pointer that you created with malloc, because it will free it when it's done with the data.
If you do not want the NSData object to take ownership, you should use dataWithBytesNoCopy:length:freeWhenDone:.
I'm trying to implement decryption of a PGP file on an iPad. I set up some test .txt files which I then encrypted via PGP desktop.
I've imported the private key of the certificate used to encrypt the document, using SecPKCS12Import, then SecIdentityCopyPrivateKey() from the resulting SecIdentityRef.
If I test encrypting and decrypting a simple string in Objective C, using the public and private key of the cert, that works perfectly.
Now that I'm trialling the actual PGP decryption, I'm a bit stumped... Reading the text from the .pgp file, I get:
-----BEGIN PGP MESSAGE-----
Version: 10.1.1.10
qANQR1DBwEwDraQm2Kxa5GkBB/4yLebeLk10C2DVvHpQL20E0DThhgQlTasXo+YJ
pLp5Ig2hHu4Xx0m74D3vfyWpA2XQA02TMAHO9lhNfkE234c/ds05D1UyQkJEoqW+
joEcbRT5rlGN3qrMf1FXv8/01EHH0dgeD6mAkkDeDEorIirYHCF6+QVkedaphZLs
c63GmcikzkWZT/vv20ICL3Ys0DaC3P9zu0T1GtjkmQ062kaTab/VBJnQrsY/y1JU
ypmbW9bbFeZMcAqXHMqpjw49K5UluIJaDbRNAjIvHTFLNuOYWVJM6FcMs5p6xqvZ
ltizeKAjr1B1h4DvbQaqdO6/OAb+dGr7fJoIHEszDsJbW1cc0lUBitrxKHrPGovF
1uEW+3glA3SopveWB4GkKzcYlbqT5y1p/gQNwY8yuZr/6iF1hyF9mx/hU/+xjOMB
og3sGX4npcQegsAMw2y+zz9kJ9a6jlteNufi
=d2Fq
-----END PGP MESSAGE-----
I know that I need to get the random one-time key, that PGP used to encrypt the file, from the data in the file. I know that to do that, I need to use SecKeyDecrypt with the private key, to obtain the one-time AES key. Once I have that key, I can then decrypt the rest of the data.
The part I'm having problems with is which part of the data to feed into SecKeyDecrypt. How is the PGP file setup - is the first 128 chars the AES key? Unless my understanding is wrong, I need to get that out separately from the data.
If I run, say, the first 128 chars as a void through the SecKeyDecrypt function: (after stripping the BEGIN PGP MESSAGE lines)
size_t dataLength = [theKey length];
size_t outputLength = MAX(128, SecKeyGetBlockSize(privateKeyRef));
void *outputBuf = malloc(outputLength);
OSStatus err;
err = SecKeyDecrypt(privateKeyRef, kSecPaddingNone,//PKCS1,
(uint8_t *)theKey, dataLength,
outputBuf, &outputLength);
if (err) {
NSLog(#"something went wrong...err = %ld", err);
}
I get this:
MRªh6∞bJ˘e£t*˝ã=ŒA¢Òt‘ŸY±éÿAÃîâG
Îfi≠$b≈tâç`yxk=uHªqu-,–dïn^™È\›5±tb.‡€Kñ⁄≤sΩw–ïʃkafS˘À*Æô竡rAyv)fi]wOrµKz^ªq“à∑öΓı*r<+l˝Äo∑›g≠¶/÷eÔ&€PÒRåêM¶Ñ|Q$á6În^võ¬∏·h(ƒß•R≤(flò(*•Aa
I don't know what encoding this is, but trying to get it from the outputBuf into a string never works 100%. It seems to get modified no matter what encoding I pass it. If I pass it to NSData first, I can get the original string back.
NSData *keyData = [NSData dataWithBytesNoCopy:outputBuf length:outputLength];
NSString *keyFromData = [[NSString alloc] initWithBytes:[keyData bytes] length:[keyData length] encoding:NSASCIIStringEncoding];
I then try to pass that key to an AES256DecryptWithKey class, providing it with the remaining data from the PGP file, after the first 128 chars.
NSData *cipherText = [[NSData alloc]initWithData:[[bodyPart objectAtIndex:1] dataUsingEncoding:NSUTF8StringEncoding]];
NSData *plain = [[NSData alloc] initWithData:[cipherText AES256DecryptWithKey:keyFromData]];
NSLog(#"after decrypting = %#", [[NSString alloc] initWithData:plain encoding:NSUTF8StringEncoding]);
Problem:
The resulting data 'plain' prints as <> i.e. empty. My problem is I don't even think I know how to grab the key from the PGP file.
Can anyone explain to me the PGP file setup? What part is the 'key' if it is in fact separate from the data at all? Is it always the same length/ same position? If it's NOT separate then I don't know how I'd be able to grab it at all. I think the rest would work fine. I'm not getting any errors or crashes, it's just NOT the right key and/or data I'm passing for AES decryption, I suspect probably a combination of string encoding error and not grabbing the right amount for the AES key/ right combination.
Note -
I created 3 different text files and ran them through the PGP process. Inspecting them, they all started with the same 24 characters (qANQR1DBwEwDraQm2Kxa5GkB). Even if I pass these 24 through the decryption, it doesn't work, and I was under the impression that the AES key PGP used was different for every single document. Did I get that wrong?
Thanks for any step in the right direction!
Edited to add:
Just noticed partly my mistake - AES of 128 requires 16 bits, so either way I am taking the wrong amount by using 128 characters, stupid mistake, think I've been looking at this too long... Swapped it out and didn't work. Any decryption I do is resulting in the '⁄Ĉ¢ï¡0M¶È2Cˆ¿©gUú¨6iîΩ`&<%Jœv£¯nRb∆:(–%' type result, which to me implies I've done something wrong OR need to do something further with encoding.
Read RFC 4880. That file is an ASCII-Armored collection of PGP packets. There are 1 or more packets that contain the symmetric key needed to decrypt the actual message, each of the symmetric key packets is encrypted with the public key of a recipient. Only people who possess the right private key can decrypt the symmetric key packet and then use that symmetric key to decrypt the rest of the message.
The AES key is indeed different.
It is randomly selected, and the encrypted with the public key system (RSA, typically).
Pub key has costs and limitations that make it unattractive to use for bulk.
You might want to look at the NetPGP, which is C code under the
BSD license, which means you can incorporate it or modify it
without encumbering your app or upsetting Apple in any way.
(Of course, contributions of source code or money would be
appreciated by the project. I'm not affiliated with them.)
The OpenPGP standard is a lot of work to implement.
Even once an implementation works, there are countless
ways in which it can be insecure.
I plan on using the AWS SDK for iOS for an upcoming project. I need to store credentials for AWS with the packed application. Where is the most secure place to place them? I know that storing them in a pList would be a bad idea. Is it better to just 'hard-code' it into a class that will be compiled? Is there any risk there?
I believe that completely hiding the credentials is theoretically impossible. That is, if your compiled code can read them, then in theory so can anyone with access to the compiled code. But imperfect security is still worth something. I'd guess that most attackers would just look through the binary for strings that look like secret keys, and not go to the trouble of decompiling the code and trying to interpret how it works, so one way to hide the credentials would be to store them in an encoded form, then decode them as needed. This way the decoding algorithm becomes your key, and an attacker would have to find and understand it to extract your credentials.
Here's a fairly simple way to do it using a random XOR mask. Replace the following bogus password with yours, and remember to keep the NULL terminator (\0) in place. Compile and run this code as a standalone program:
#include <stdio.h>
#define PAD_LENGTH 32
int main() {
int i;
char c;
// start with the password
char password[PAD_LENGTH] = "My AWS Password\0";
// make a random pad to encrypt it
printf("PAD:\n{");
char pad[PAD_LENGTH];
for (i = 0; i < PAD_LENGTH; i++) {
c = arc4random() & 0xFF;
pad[i] = c;
printf("%#02x", c & 0xFF);
if (i < PAD_LENGTH - 1) printf(",");
}
printf("}\n");
// make an encrypted version of the password
printf("KEY:\n{");
for (i = 0; i < PAD_LENGTH; i++) {
c = pad[i] ^ password[i];
printf("%#02x", c & 0xFF);
if (i < PAD_LENGTH - 1) printf(",");
}
printf("}\n");
return(0);
}
Then copy the generated pad and key into code like this (which will actually get included with your app):
#define PAD_LENGTH 32
char pad[PAD_LENGTH] = {0x83,0x26,0x8a,0x8b,0xee,0xab,0x6,0xed,0x2e,0x99,0xff,0x23,0x7f,0xef,0xc8,0x8,0x6b,0x8e,0xa4,0x64,0x6d,0xb,0x7,0xd2,0x6a,0x39,0x60,0xa4,0xa9,0xad,0xea,0xb8};
char key[PAD_LENGTH] = {0xce,0x5f,0xaa,0xca,0xb9,0xf8,0x26,0xbd,0x4f,0xea,0x8c,0x54,0x10,0x9d,0xac,0x8,0x6b,0x8e,0xa4,0x64,0x6d,0xb,0x7,0xd2,0x6a,0x39,0x60,0xa4,0xa9,0xad,0xea,0xb8};
for (int i = 0; i < PAD_LENGTH; i++) {
key[i] = key[i] ^ pad[i];
}
NSString *password = [NSString stringWithCString:key encoding:NSASCIIStringEncoding];
Since this is on a public forum, you might want to change a few things, like making the pads a different length, splitting them up and rejoining them with code, reordering them, etc. You could also store the pad and key in distant parts of the code. A truly skilled and dedicated attacker is going to be able to find your password no matter what, but the basic idea is that most people scanning the binary for a password will not find it as such.
Have you looked at the Data Protection API?
What are the new "iOS data protection APIs"?
There are various options depending on your security needs.
This question may help also.
Data Protection on iOS
The video from a conference this year was useful.
http://developer.apple.com/videos/wwdc/2010
you should use AWS Identity and Access Management (IAM): http://aws.amazon.com/iam/
you can find more information about AWS Credential Management in Mobile Applications on http://aws.amazon.com/articles/4611615499399490