I am trying to write code for generating globally unique name for images that are to be uploaded by users from iOS app to server. The names should be randomly generated and should be unique so that the images are not overwritten/replaced.
Here's my code for generating random and unique strings:
+ (NSString *)generateRandNameWithLength:(int)len
{
NSString *letters = [NSString stringWithFormat:#"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ%#0123456789", [HJUtilities generateUniqueApId]];
NSMutableString *randomString = [NSMutableString stringWithCapacity: len];
for (int i=0; i<len; i++) {
[randomString appendFormat: #"%C", [letters characterAtIndex: arc4random() % [letters length]]];
}
return randomString;
}
Where:
+ (NSString *)generateUniqueApId
{
NSString *appId = (__bridge NSString *) CFUUIDCreateString (NULL, CFUUIDCreate(NULL));
return appId;
}
returns a UUID.
Now I'm not sure whether this is the correct code for generating globally unique strings. I don't know how to verify this to be certain that no user will overwrite another user's image.
Note: I'm using Amazon Web services for storage. And one common bucket will be used for all the images of all users. So, its required that images names should be unique.
There is no need for the code you have. All you need is the CFUUIDCreateString function. This will be unique across all users on all devices.
From the docs for CFUUID:
UUIDs (Universally Unique Identifiers), also known as GUIDs (Globally Unique Identifiers) or IIDs (Interface Identifiers), are 128-bit values guaranteed to be unique. A UUID is made unique over both space and time by combining a value unique to the computer on which it was generated—usually the Ethernet hardware address—and a value representing the number of 100-nanosecond intervals since October 15, 1582 at 00:00:00.
The code you have now is definitely not guaranteed to be unique.
There is a new class added in iOS 6.0
#interface NSUUID : NSObject <NSCopying, NSSecureCoding>
To simplify the memory management you for sure can use it
You're overcomplicating it. Just get a UUID using CFUUIDCreateString and use that string. Adding extra layers of randomness isn't going to help. In fact, it's probably going to make things worse by increasing the chance of a name collision.
The only argument against using a UUID directly is that it may be possible to identify the source of the upload, since the UUID is (or can be) generated using device's MAC address, which is specific to the hardware. You won't be able to identify a user with nothing but a UUID, but you would be able to say "this collection of UUIDs came from the same device" or "this UUID came from this device". (See RFC 4122 for the various UUID formats and a discussion of this issue in section 4.5.)
If anonymity is a concern, running the UUID through a hash function, like SHA1 or MD5, would be good enough to make it unidentifiable.
Using a loop where you "add randomness" by mixing in random numbers is like shaking a dice for a few seconds versus an hour: the only difference is that you're rubbing sweat onto the dice.
As far as a locally unique string — which you could use as part of the file name — this is handy:
[[NSProcessInfo processInfo] globallyUniqueString]
Related
I'm new to Iphone developing. I have next problem:
I need to get unique id for every iPhone that runs my application.
I found this great project on github:
https://github.com/gekitz/UIDevice-with-UniqueIdentifier-for-iOS-5
These functions return string of 32 characters which represents some hexadecimal value.
Does someone have an idea how could I get unsigned long long value (64bit integer value) from this string?
Thanks
Please note that as for iOS 5, getting the device's UUID is deprecated by Apple and unless you're working on an in-house project, you should not do it. Apple apparently started rejecting apps doing it with no proper reason.
The best way to uniquely identify your users is by generating a GUID at startup. Please see this SO thread : UIDevice uniqueIdentifier Deprecated - What To Do Now?
You cannot fit 32 unicode characters (every one has 2 bytes, that is 64 bytes in total) into a long long which has only 8 bytes.
Luzal is right...getting the device's UDID is deprecated by Apple.
You also can use the OPEN UDID for uniquely identify your users..
downloads the classes from here-
https://github.com/ylechelle/OpenUDID
import the class -
#import "OpenUDID.h"
and use below code to get OPEN UDID
NSString * uniqueStr = [OpenUDID value];
NSLog(#"%#",uniqueStr);
I am making an Iphone drinking card game app.
All the card mean something different and i want the user to be able to press an info button and then show a new screen with information about the current card. How can i make a document to load text from instead of using a bunch og long strings?
Thanks
You could look into plist files - they can be loaded quite easily into the various collection objects and edited with the plist editor in Xcode.
For instance, if you organize your data as a dictionary, the convenience constructor
+ (id)dictionaryWithContentsOfURL:(NSURL *)aURL
from NSDictionary would provide you with as many easily accessible strings as you need.
This method is useful if you consider your strings primarily data as opposed to UI elements.
Update:
As #Alex Nichol suggested, here is how you can do it in practice:
To create a plist file:
In your Xcode project, for instance in the Supporting Files group, select New File > Resource > Property List
You can save the file in en.lproj, to aid in localization
In the Property list editing pane, select Add Row (or just hit return)
Enter a key name (for instance user1) and a value (for instance "Joe")
To read the contents:
NSURL *plistURL = [[NSBundle mainBundle] URLForResource:#"Property List" withExtension:#"plist"];
NSLog(#"URL: %#", plistURL);
NSDictionary *strings = [NSDictionary dictionaryWithContentsOfURL:plistURL];
NSString *user1 = [strings objectForKey:#"user1"];
NSLog(#"User 1: %#", user1);
A plist, a JSON string, and an SQLite database walked into a bar ...
Oops!! I mean those are the three most obvious alternatives. The JSON string is probably the easiest to create and "transport", though it's most practical to load the entire thing into an NSDictionary and/or NSArray, vs read from the file as each string is accessed.
The SQLite DB is the most general, and most speed/storage efficient for a very large number (thousands) of strings, but it takes some effort to set it up.
In my other answer, I suggest the use of a dictionary if your texts are mostly to be considered as data. However, if your strings are UI elements (alert texts, window titles, etc.) you might want to look into strings files and NSBundle's support for them.
Strings files are ideally suited for localization, the format is explained here.
To read them into you app, use something like this:
NSString *text1 = NSLocalizedStringFromTable(#"TEXT1", #"myStringsFile", #"Comment");
If you call your file Localizable.strings, you can even use a simpler form:
NSString *str1 = NSLocalizedString(#"String1", #"Comment on String1");
A useful discussion here - a bit old, but still useful.
What would be the best way to name a file associated to a NSManagedObject. The NSManagedObject will hold the URL to this file.
But I need to create a unique filename for my file. Is there some kind of autoincrement id that I could use? Should I use mktemp (but it's not a temporary file) or try to convert the NSManagedObjectId to a filename? but I fear there will be special characters which might cause problem.
What would you suggest?
EDIT: I have a lot of these NSManagedObjects and each has its own image, so I want to generate a unique name for each picture.
You can use NSProcessInfo to generated the guid:
[[NSProcessInfo processInfo] globallyUniqueString]
And to reference a file I'd suggest just keeping the guid as NSManagedObject property and then just reference a file by that name from application support directory.
There is a good way to do this and one earlier answer almost had it – generate a GUID for each image instead of for the entire process. Call this method whenever you need a unique string, and then store it in the managed object:
+ (NSString *)getUUID
{
CFUUIDRef theUUID = CFUUIDCreate(NULL);
CFStringRef string = CFUUIDCreateString(NULL, theUUID);
CFRelease(theUUID);
return [(NSString *)string autorelease];
}
I use this for storing captured movies and images.
I thought about using the time to generate a unique filename but I don't like the solution, for instance if the time is reset or changed, there is a slight chance of getting two times the same filename.
I'm surprised not to find more information about this subject on the web.
Since iOS5 there is now the option to store large blobs in an external record file. CoreData decides whether or not to store the record in sqlite based on the size of the record.
Storing blobs in external location using built-in CoreData option
I found this in my travels:
http://www.opensource.apple.com/source/IOKitUser/IOKitUser-502/ps.subproj/IOPSKeys.h
How would I get the values (as a number) of:
#define kIOPSMaxCapacityKey "Max Capacity"
and
#define kIOPSDesignCapacityKey "DesignCapacity"
I want to be able to use them throughout my app. What do I need to add to my project and how do extract the numbers?
Many thanks,
Stuart
Once you know where the actual dictionary is that it's storing these values, you can access the value from the dictionary using the following call:
CFDictionaryGetValue (
CFDictionaryRef theDict,
const void *key
);
Further examination of the directory http://www.opensource.apple.com/source/IOKitUser/IOKitUser-502/ps.subproj/ would probably allow you to figure out which objects/methods to call to get the dictionary, and the documentation within the class states what it points to (in your two previously mentioned keys, they point to CFNumbers, so in that case CFDictionaryGetValue will return a CFNumber.
I need to store passwords in NSString objects; however, I would like some way to obfuscate them, so they cannot be read directly from memory.
This is a Mac OS X (10.5) application, but a solution that also works on iPhone would be much appreciated.
If you use the keychain for storing passwords then instead of passing strings around you could handle the opaque keychain SecKeychainItemRefs, only retrieving plaintext at the point where it's required. That's also the way Mac users expect their passwords to be dealt with. Unfortunately without knowing why you "need to store passwords in NSString objects" I can't tell if that's really true :-)
Couldn't you just md5 them before putting them in the NSString? Then when you go to test, md5 the input string and compare that with what is stored?
On the iPhone, the sandbox will stop anyone accessing your passwords. on the desktop it's not so easy.
You should store the passwords as hashes rather than cleartext. I believe this will get you the results you want without affecting functionality. The only think you will never be able to do is access the cleartext password again - if you want to analyse it for strength or pass it on to another service. In general though, hashes will not sacrifice functionality.
The following code takes a password in rawPassword and stores its SHA-1 hash in passwordHash.
#import <CommonCrypto/CommonDigest.h>
const char* utf8PasswordRepresentation = [rawPassword UTF8String];
unsigned char * rawHash = malloc(CC_SHA1_DIGEST_LENGTH);
CC_SHA1(utf8PasswordRepresentation, strlen(utf8PasswordRepresentation), rawHash);
NSMutableString* passwordHash = [NSMutableString CC_SHA1_DIGEST_LENGTH*2];
for (int i = 0 ; i< CC_SHA1_DIGEST_LENGTH; i++)
[passwordHash appendFormat:#"%02x" , rawHash[i]];
Note that there is no memory management here.
Check out the wikipedia entry for an explanation of password hashing.
There are many versions of this same code around the intertubes.
I think the poster is referring to obfuscating the password in memory, so you can't just read the contents of the ivar out of memory. The GData library from google has some useful code for XORing passwords stored as NSMutableData in instance variables.
source for GDataServiceBase.m
// XorPlainMutableData is a simple way to keep passwords held in heap objects
// from being visible as plain-text
static void XorPlainMutableData(NSMutableData *mutable) {
// this helps avoid storing passwords on the heap in plaintext
const unsigned char theXORValue = 0x95; // 0x95 = 0xb10010101
unsigned char *dataPtr = [mutable mutableBytes];
NSUInteger length = [mutable length];
for (NSUInteger idx = 0; idx < length; idx++) {
dataPtr[idx] ^= theXORValue;
}
}
You can save/restore the password using XOR (see #password and #setUserCredentialsWithUsername:password: methods in the same file). XOR is not high-tech encryption, but it's good enough to deter casual snooping. In the case of the GData client where you might have a long-lived service/manager object in an application that retains a reference to the password data, I think this is a reasonable approach.
A very useful set of code for storing and retrieving passwords to and from the keychain can be found here:
http://log.scifihifi.com/post/55837387/simple-iphone-keychain-code
I've used it, and it worked well.