This is the code I am using for the encryption but it generate an error
"CCKeyDerivationPBKDF is unavailable" in AESKeyForPassword method though it is declare before implementation. How to Resolve it.
#ifndef _CC_PBKDF_H_
#define _CC_PBKDF_H_
#include <sys/types.h>
#include <sys/param.h>
#include <string.h>
#include <limits.h>
#include <stdlib.h>
#include <Availability.h>
#include <CommonCrypto/CommonDigest.h>
#include <CommonCrypto/CommonHMAC.h>
#ifdef __cplusplus
extern "C" {
#endif
enum {
kCCPBKDF2 = 2,
};
typedef uint32_t CCPBKDFAlgorithm;
enum {
kCCPRFHmacAlgSHA1 = 1,
kCCPRFHmacAlgSHA224 = 2,
kCCPRFHmacAlgSHA256 = 3,
kCCPRFHmacAlgSHA384 = 4,
kCCPRFHmacAlgSHA512 = 5,
};
typedef uint32_t CCPseudoRandomAlgorithm;
/*
#function CCKeyDerivationPBKDF
#abstract Derive a key from a text password/passphrase
#param algorithm Currently only PBKDF2 is available via kCCPBKDF2
#param password The text password used as input to the derivation
function. The actual octets present in this string
will be used with no additional processing. It's
extremely important that the same encoding and
normalization be used each time this routine is
called if the same key is expected to be derived.
#param passwordLen The length of the text password in bytes.
#param salt The salt byte values used as input to the derivation
function.
#param saltLen The length of the salt in bytes.
#param prf The Pseudo Random Algorithm to use for the derivation
iterations.
#param rounds The number of rounds of the Pseudo Random Algorithm
to use.
#param derivedKey The resulting derived key produced by the function.
The space for this must be provided by the caller.
#param derivedKeyLen The expected length of the derived key in bytes.
#discussion The following values are used to designate the PRF:
* kCCPRFHmacAlgSHA1
* kCCPRFHmacAlgSHA224
* kCCPRFHmacAlgSHA256
* kCCPRFHmacAlgSHA384
* kCCPRFHmacAlgSHA512
#result kCCParamError can result from bad values for the password, salt,
and unwrapped key pointers as well as a bad value for the prf function.
*/
int CCKeyDerivationPBKDF( CCPBKDFAlgorithm algorithm, const char *password, size_t passwordLen,
const uint8_t *salt, size_t saltLen,
CCPseudoRandomAlgorithm prf, uint rounds,
uint8_t *derivedKey, size_t derivedKeyLen)
__OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA);
/*
* All lengths are in bytes - not bits.
*/
/*
#function CCCalibratePBKDF
#abstract Determine the number of PRF rounds to use for a specific delay on
the current platform.
#param algorithm Currently only PBKDF2 is available via kCCPBKDF2
#param passwordLen The length of the text password in bytes.
#param saltLen The length of the salt in bytes.
#param prf The Pseudo Random Algorithm to use for the derivation
iterations.
#param derivedKeyLen The expected length of the derived key in bytes.
#param msec The targetted duration we want to achieve for a key
derivation with these parameters.
#result the number of iterations to use for the desired processing time.
*/
uint CCCalibratePBKDF(CCPBKDFAlgorithm algorithm, size_t passwordLen, size_t saltLen,
CCPseudoRandomAlgorithm prf, size_t derivedKeyLen, uint32_t msec)
__OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA);
#ifdef __cplusplus
}
#endif
#endif /* _CC_PBKDF_H_ */
#import "AESEncryption.h"
#import <CommonCrypto/CommonCryptor.h>
//#import <CommonCrypto/CommonKeyDerivation.h>
//#import <CommonKeyDerivation.h>
#implementation AESEncryption
NSString * const
kRNCryptManagerErrorDomain = #"net.robnapier.RNCryptManager";
const CCAlgorithm kAlgorithm = kCCAlgorithmAES128;
const NSUInteger kAlgorithmKeySize = kCCKeySizeAES128;
const NSUInteger kAlgorithmBlockSize = kCCBlockSizeAES128;
const NSUInteger kAlgorithmIVSize = kCCBlockSizeAES128;
const NSUInteger kPBKDFSaltSize = 8;
const NSUInteger kPBKDFRounds = 1000;//0; // ~80ms on an iPhone 4
// ===================
+ (NSData *)encryptedDataForData:(NSData *)data
password:(NSString *)password
iv:(NSData **)iv
salt:(NSData **)salt
error:(NSError **)error {
NSAssert(iv, #"IV must not be NULL");
NSAssert(salt, #"salt must not be NULL");
*iv = [self randomDataOfLength:kAlgorithmIVSize];
*salt = [self randomDataOfLength:kPBKDFSaltSize];
NSData *key = [self AESKeyForPassword:password salt:*salt];
size_t outLength;
NSMutableData *
cipherData = [NSMutableData dataWithLength:data.length +
kAlgorithmBlockSize];
CCCryptorStatus
result = CCCrypt(kCCEncrypt, // operation
kAlgorithm, // Algorithm
kCCOptionPKCS7Padding, // options
key.bytes, // key
key.length, // keylength
(*iv).bytes,// iv
data.bytes, // dataIn
data.length, // dataInLength,
cipherData.mutableBytes, // dataOut
cipherData.length, // dataOutAvailable
&outLength); // dataOutMoved
if (result == kCCSuccess) {
cipherData.length = outLength;
}
else {
if (error) {
*error = [NSError errorWithDomain:kRNCryptManagerErrorDomain
code:result
userInfo:nil];
}
return nil;
}
return cipherData;
}
// ===================
+ (NSData *)randomDataOfLength:(size_t)length {
NSMutableData *data = [NSMutableData dataWithLength:length];
int result = SecRandomCopyBytes(kSecRandomDefault, length,data.mutableBytes);
NSLog(#"%d",result);
NSAssert1(result == 0, #"Unable to generate random bytes: %d", errno);
//NSAssert( #"Unable to generate random bytes: %d", errno);
return data;
}
// ===================
// Replace this with a 10,000 hash calls if you don't have CCKeyDerivationPBKDF
+ (NSData *)AESKeyForPassword:(NSString *)password
salt:(NSData *)salt {
NSMutableData *
derivedKey = [NSMutableData dataWithLength:kAlgorithmKeySize];
int result = CCKeyDerivationPBKDF(kCCPBKDF2, // algorithm
password.UTF8String, // password
password.length, // passwordLength
salt.bytes, // salt
salt.length, // saltLen
kCCPRFHmacAlgSHA1, // PRF
kPBKDFRounds, // rounds
derivedKey.mutableBytes, // derivedKey
derivedKey.length); // derivedKeyLen
NSLog(#"%d",result);
// Do not log password here
NSAssert1(result == kCCSuccess,#"Unable to create AES key for password: %d", result);
//NSAssert(#"Unable to create AES key for password: %d", result);
return derivedKey;
}
#end
The code placed above implementation is of CommonCrypto/CommonKeyDerivation.h which was not found be me xcode and hence I put code directly at the top.
Try to comment out this lines:
__OSX_AVAILABLE_STARTING(__MAC_10_7, __IPHONE_NA);
I think they limit the method to a particular Operating System and this is exactly what you don't need.
But I cannot guarantee if further issues may appear. I'm trying to achieve the same.
You have merely declared 2 prototypes for CCKeyDerivationPBKDF and CCCalibratePBKDF. Either put the full code for the functions at this place or declare them as extern and have them in a seperate module or library.
Related
I am looking at the file attached here GSEvent.h:
I am interesting to know the following params when the user press the screen.
i.e like pathPressure pathMajorRadius pathProximity etc.. (I do not want to set these values by myself, but to receive them from the user when he/she press the screen.)
typedef struct GSPathInfo {
unsigned char pathIndex; // 0x0 = 0x5C
unsigned char pathIdentity; // 0x1 = 0x5D
unsigned char pathProximity; // 0x2 = 0x5E
CGFloat pathPressure; // 0x4 = 0x60
CGFloat pathMajorRadius; // 0x8 = 0x64
CGPoint pathLocation; // 0xC = 0x68
GSWindowRef pathWindow; // 0x14 = 0x70
} GSPathInfo; // sizeof = 0x18.
If I am looking down below the file (GSEvent.h)
GSPathInfo GSEventGetPathInfoAtIndex(GSEventRef event, CFIndex index);
I was wonder what I need to put in the GSEventRef event and CFIndex index
So I searched for GSEventRef scrolling to the top of the file I saw it is a pointer to __GSEvent
typedef struct __GSEvent* GSEventRef;
I am stuck here, what event do I create and how ...
GSEventRef* eventRef = malloc(sizeof(GSEventRef));
Or I need to do something like
__GSEvent* GSEventRef = malloc(sizeof(__GSEvent));
After allocating memory how do I set it ? I mean what value should I set for it?
If I have a character string, how can I convert the values to hexadecimal in Objective-C? Likewise, how can I convert from a hexadecimal string to a character string?
As an exercise and in case it helps, I wrote a program to demonstrate how I might do this in pure C, which is 100% legal in Objective-C. I used the string-formatting functions in stdio.h to do the actual conversions.
Note that this can (should?) be tweaked for your setting. It will create a string twice as long as the passed-in string when going char->hex (converting 'Z' to '5a' for instance), and a string half as long going the other way.
I wrote this code in such a way that you can simply copy/paste and then compile/run to play around with it. Here is my sample output:
My favorite way to include C in XCode is to make a .h file with the function declarations separate from the .c file with implementation. See the comments:
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
// Place these prototypes in a .h to #import from wherever you need 'em
// Do not import the .c file anywhere.
// Note: You must free() these char *s
//
// allocates space for strlen(arg) * 2 and fills
// that space with chars corresponding to the hex
// representations of the arg string
char *makeHexStringFromCharString(const char*);
//
// allocates space for about 1/2 strlen(arg)
// and fills it with the char representation
char *makeCharStringFromHexString(const char*);
// this is just sample code
int main() {
char source[256];
printf("Enter a Char string to convert to Hex:");
scanf("%s", source);
char *output = makeHexStringFromCharString(source);
printf("converted '%s' TO: %s\n\n", source, output);
free(output);
printf("Enter a Hex string to convert to Char:");
scanf("%s", source);
output = makeCharStringFromHexString(source);
printf("converted '%s' TO: %s\n\n", source, output);
free(output);
}
// Place these in a .c file (named same as .h above)
// and include it in your target's build settings
// (should happen by default if you create the file in Xcode)
char *makeHexStringFromCharString(const char*input) {
char *output = malloc(sizeof(char) * strlen(input) * 2 + 1);
int i, limit;
for(i=0, limit = strlen(input); i<limit; i++) {
sprintf(output + (i*2), "%x", input[i]);
}
output[strlen(input)*2] = '\0';
return output;
}
char *makeCharStringFromHexString(const char*input) {
char *output = malloc(sizeof(char) * (strlen(input) / 2) + 1);
char sourceSnippet[3] = {[2]='\0'};
int i, limit;
for(i=0, limit = strlen(input); i<limit; i+=2) {
sourceSnippet[0] = input[i];
sourceSnippet[1] = input[i+1];
sscanf(sourceSnippet, "%x", (int *) (output + (i/2)));
}
output[strlen(input)/2+1] = '\0';
return output;
}
I am making a C program that supports many languages. The program send emails using the type WCHAR instead of char. The problem is that when I receive the email and read it, some characters are not shown correctly, even some English ones like e, m, ... This is an example:
<!-- language: lang-c -->
curl_easy_setopt(hnd, CURLOPT_READFUNCTION, payload_source);
curl_easy_setopt(hnd, CURLOPT_READDATA, &upload_ctx);
static const WCHAR *payload_text[]={
L"To: <me#mail.com>\n",
L"From: <me#mail.com>(Example User)\n",
L"Subject: Hello!\n",
L"\n",
L"Message sent\n",
NULL
};
struct upload_status {
int lines_read;
};
static size_t payload_source(void *ptr, size_t size, size_t nmemb, void *userp){
struct upload_status *upload_ctx = (struct upload_status *)userp;
const WCHAR *data;
if ((size == 0) || (nmemb == 0) || ((size*nmemb) < 1)) {
return 0;
}
data = payload_text[upload_ctx->lines_read];
if (data) {
size_t len = wcslen(data);
memcpy(ptr, data, len);
upload_ctx->lines_read ++;
return len;
}
return 0;
}
memcpy() operates on bytes, not on characters. You are not taking into account that sizeof(wchar_t) > 1. It is 2 bytes on some systems and 4 bytes on others. This descrepency makes wchar_t a bad choice when writing portable code. You should be using a Unicode library instead, such as icu or iconv).
You need to take sizeof(wchar_t) into account when calling memcpy(). You also need to take into account that the destination buffer may be smaller than the size of the text bytes you are trying to copy. Keeping track of the lines_read by itself is not enough, you have to also keep track of how many bytes of the current line you have copied so you can handle cases when the current line of text straddles across multiple destination buffers.
Try something more like this instead:
static size_t payload_source(void *ptr, size_t size, size_t nmemb, void *userp)
{
struct upload_status *upload_ctx = (struct upload_status *) userp;
unsigned char *buf = (unsignd char *) ptr;
size_t available = (size * nmemb);
size_t total = 0;
while (available > 0)
{
wchar_t *data = payload_text[upload_ctx->lines_read];
if (!data) break;
unsigned char *rawdata = (unsigned char *) data;
size_t remaining = (wcslen(data) * sizeof(wchar_t)) - upload_ctx->line_bytes_read;
while ((remaining > 0) && (available > 0))
{
size_t bytes_to_copy = min(remaining, available);
memcpy(buf, rawdata, bytes_to_copy);
buf += bytes_to_copy;
available -= bytes_to_copy;
total = bytes_to_copy;
rawdata += bytes_to_copy;
remaining -= bytes_to_copy;
upload_ctx->line_bytes_read += bytes_to_copy;
}
if (remaining < 1)
{
upload_ctx->lines_read ++;
upload_ctx->line_bytes_read = 0;
}
}
return total;
}
I have a NSData object coming back from my server, it varies in its content but sticks to a particular structure.
I would like to know (hopfully with some example code) how to work though this object to get the data I need out of it.
the structure of the data objects inside the objects are like this
leading value (UInt16) - (tells me what section of the response it is)
Size of string (UInt32) or number - (UInt32)
String (not null terminated) i.e. followed by the next leading value.
I have been reading through the Binary Data Programming Guide however that's only really showing me how to put my data into new NSData objects and accessing and compairing the bytes.
The thing I am stuck on is how do I say grab the info dynamically. Check the NSdata objects first leading value figure out if its string or int then get the string or int and move onto the next leading value..
any suggestions or example code would be really helpfull.. just stuck in abit of a mind block as I have never attempted anything like this in objective C.
Some of this depends on how your server is written to encode the data into what it is sending you. Assuming it is encoding the numeric values using standard network byte ordering (big-endian) you will want it converted to the correct byte-ordering for iOS (I believe that is always little-endian).
I would approach it something like this:
uint16_t typeWithNetworkOrdering, typeWithLocalOrdering;
uint32_t sizeWithNetworkOrdering, sizeWithLocalOrdering;
char *cstring = NULL;
uint32_t numberWithNetworkOrdering, numberWithLocalOrdering;
const void *bytes = [myData bytes];
NSUInteger length = [myData length];
while (length > 0) {
memcpy(&typeWithNetworkOrdering, bytes, sizeof(uint16_t));
bytes += sizeof(uint16_t);
length -= sizeof(uint16_t);
memcpy(&sizeWithNetworkOrdering, bytes, sizeof(uint32_t));
bytes += sizeof(uint32_t);
length -= sizeof(uint32_t);
typeWithLocalOrdering = CFSwapInt16BigToHost(typeWithNetworkOrdering);
sizeWithLocalOrdering = CFSwapInt32BigToHost(sizeWithNetworkOrdering);
if (typeWithLocalOrdering == STRING_TYPE) { // STRING_TYPE is whatever type value corresponds to a string
cstring = (char *) malloc(sizeWithLocalOrdering + 1);
strncpy(cstring, bytes, sizeWithLocalOrdering);
cstring[sizeWithLocalOrdering] = '\0';
NSString *resultString = [NSString stringWithCString:cstring encoding:NSUTF8StringEncoding];
NSLog(#"String = %#", resultString);
free(cstring);
bytes += sizeWithLocalOrdering;
length -= sizeWithLocalOrdering;
// Do whatever you need to with the string
}
else if (typeWithLocalOrdering == NUMBER_TYPE) { // NUMBER_TYPE is whatever type value corresponds to a number
memcpy(&numberWithNetworkOrdering, bytes, sizeof(uint32_t));
numberWithLocalOrdering = CFSwapInt32BigToHost(numberWithNetworkOrdering);
NSLog(#"Number = %u", numberWithLocalOrdering);
bytes += sizeof(uint32_t);
length -= sizeof(uint32_t);
// Do whatever you need to with the number
}
}
Define your own internal structs and cast the pointer to it:
NSData* data;
struct headerType
{
uint16_t type;
uint32_t length;
};
const struct headerType* header=(const struct headerType*)[data bytes]; // get the header of the response
if (header->type==1)
{
const char* text=((const char*)header)+6; // skip the header (16bits+32bits=6 bytes offset)
}
EDIT:
If you need to read them in a loop:
NSData* data;
const uint8_t* cursor=(const uint8_t*)[data bytes];
while (true)
{
uint16_t type=*((uint16_t*)cursor);
cursor+=2;
if (cursor==1)
{
// string
uint32_t length=*((uint32_t*)cursor);
cursor+=4;
const char* str=(const char*)cursor;
cursor+=length;
}
else if (cursor==2)
{
// another type
}
else
break;
}
I am doing a file uploading job. I want to generate SHA256 and CRC32 hashes. Can anyone help me how shall I generate those hash? I want to get it working for iOS.
SHA256 is available in CommonCrypto. CRC32 is not a hash, it a Cyclic Redundancy Check.
Example code:
#import <CommonCrypto/CommonDigest.h>
NSData *dataIn = [#"Now is the time for all good computers to come to the aid of their masters." dataUsingEncoding:NSASCIIStringEncoding];
NSMutableData *macOut = [NSMutableData dataWithLength:CC_SHA256_DIGEST_LENGTH];
CC_SHA256(dataIn.bytes, dataIn.length, macOut.mutableBytes);
NSLog(#"dataIn: %#", dataIn);
NSLog(#"macOut: %#", macOut);
NSLog output:
dataIn: <4e6f7720 69732074 68652074 696d6520 666f7220 616c6c20 676f6f64 20636f6d 70757465 72732074 6f20636f 6d652074 6f207468 65206169 64206f66 20746865 6972206d 61737465 72732e>
macOut: <53f89cf6 7ebfbe56 89f1f76a 3843dfd1 09d68c5b a938dcd2 9a12004e 108260cb>
For both of these, you can use this gist:
https://gist.github.com/paul-delange/6808278
And an example
NSString* crc32 = (__bridge NSString*)TGDFileHashCreateWithPath((__bridge CFStringRef)filepath, TGDFileHashDefaultChunkSizeForReadingData, TGDChecksumAlgorithmCRC32);
This method will generate crc32c as used by gcloud on iOS from a filepath. If you want the standard crc32 just uncomment the other value for CRC32_POLYNOMIAL.
It reads the file given in 512KB chunks so can be used on large files.
- (NSString*) crc32c:(NSString*)filepath{
/// using crc code from
// http://classroomm.com/objective-c/index.php?action=printpage;topic=2891.0
// by rgronlie
//this is the standard crc32 polynomial
//uint32_t CRC32_POLYNOMIAL = 0xEDB88320;
//this is the crc32c one
uint32_t CRC32_POLYNOMIAL = 0x82F63B78L;
uint32_t CRC32C_SEED = 0xFFFFFFFFL;
// create and populate a lookup table
uint32_t* pCRCTable = malloc(sizeof(uint32_t) * 256);
for (uint32_t i = 0; i <= 255; i++)
{
uint32_t crc32 = i;
for (uint32_t j = 8; j > 0; j--)
{
if ((crc32 & 1) == 1)
crc32 = (crc32 >> 1) ^ CRC32_POLYNOMIAL;
else
crc32 >>= 1;
}
pCRCTable[i] = crc32;
}
// get a handle to the file
NSFileHandle *filehandle = [NSFileHandle fileHandleForReadingAtPath:filepath];
if(filehandle == NULL){
NSLog(#"failed to create file handle");
return nil;
}
// a buffer to read into
NSData* databuffer;
uint32_t crc = CRC32C_SEED;
// read the file in chunks of 512KB
while(true){
databuffer = [filehandle readDataOfLength: 512 * 1024];
// if there is nothing left finish
if([databuffer length] == 0){
break;
}
// otherwise run each chunk through the lookup table
uint8_t *pBytes = (uint8_t *)[databuffer bytes];
uint32_t length = [databuffer length];
while (length--)
{
crc = (crc>>8) ^ pCRCTable[(crc & 0xFF) ^ *pBytes++];
}
}
// clean up
[filehandle closeFile];
free(pCRCTable);
// this is the result
uint32_t hash = crc ^ 0xFFFFFFFFL;
// reverse it for endianness
uint32_t hash_reversed = CFSwapInt32HostToBig(hash);
// as raw bytes
NSData* hash_data = [NSData dataWithBytes: &hash_reversed length: sizeof(hash_reversed)];
// return base64 encoded
return [hash_data base64EncodedStringWithOptions:0];
}
there are no apps which can generate Hash for ios
This should work....its for Mac
http://itunes.apple.com/us/app/digiprint/id473233587?mt=12