I am building an iPhone app which gets a encrypt string and sent it to backend.
In PHP I am encrypting the string like this:
$encrypt_method = "AES-256-CBC";
$secret_key = 'This is my secret key';
$secret_iv = 'This is my secret iv';
// hash
$key = hash('sha256', $secret_key);
// iv - encrypt method AES-256-CBC expects 16 bytes - else you will get a warning
$iv = substr(hash('sha256', $secret_iv), 0, 16);
if( $action == 'encrypt' ) {
$output = openssl_encrypt($string, $encrypt_method, $key, 0, $iv);
$output = base64_encode($output);
}
How I do the same like that but in Objective C
#import <CommonCrypto/CommonCryptor.h>
#define key #"YOUR_KEY"
#define iv #"YOUR_IV"
- (NSData *) cryptOperation:(CCOperation)operation
{
// 'key' should be 32 bytes for AES256, will be null-padded otherwise
char keys[kCCKeySizeAES256 + 1];
[key getCString:keys maxLength:sizeof(keys) encoding:NSUTF8StringEncoding];
// Perform PKCS7Padding on the key.
unsigned long bytes_to_pad = sizeof(keys) - [key length];
if (bytes_to_pad > 0)
{
char byte = bytes_to_pad;
for (unsigned long i = sizeof(keys) - bytes_to_pad; i < sizeof(keys); i++)
keys[i] = byte;
}
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's why we need to add the size of one block here
size_t bufferSize = dataLength + kCCBlockSizeAES128;
void *buffer = malloc(bufferSize);
size_t numBytesDecrypted = 0;
CCCryptorStatus status = CCCrypt(operation, kCCAlgorithmAES128,
kCCOptionPKCS7Padding,
keys, kCCKeySizeAES256,
[iv UTF8String],
[self bytes], dataLength, /* input */
buffer, bufferSize, /* output */
&numBytesDecrypted);
if (status == kCCSuccess)
{
//the returned NSData takes ownership of buffer and will free it on dealloc
return [NSData dataWithBytesNoCopy:buffer length:numBytesDecrypted];
}
free(buffer); //free the buffer;
return nil;
}
- (NSData *)AES256Encrypt
{
return [self cryptOperation:kCCEncrypt];
}
- (NSData *)AES256Decrypt
{
return [self cryptOperation:kCCDecrypt];
}
you can use this method by following way..
NSString *receivedDataDecryptString = [self decrypt:#"YOUR_STRING"];
NSString *receivedDataEncryptString = [self encrypt:#"YOUR_STRING"];
-(NSString *)encrypt:(NSString *)string
{
NSData *data = [string dataUsingEncoding:NSUTF8StringEncoding];
NSData *dataEncrypted = [data AES256Encrypt];
NSString *strRecordEncrypted = [dataEncrypted base64EncodedStringWithOptions:0];
return strRecordEncrypted;
}
-(NSString *)decrypt:(NSString *)string
{
if([string containsString:#"\n"] || [string containsString:#"\t"])
{
string = [[string componentsSeparatedByCharactersInSet:[NSCharacterSet newlineCharacterSet]] componentsJoinedByString:#""];
string = [string stringByReplacingOccurrencesOfString:#"\t" withString:#""];
}
NSData *keyData = [[NSData alloc] initWithBase64EncodedString:string options:0];
NSData *dataDecrypted = [keyData AES256Decrypt];
NSString *receivedDataDecryptString = [[NSString alloc]initWithData:dataDecrypted encoding:NSUTF8StringEncoding];
return receivedDataDecryptString;
}
Thanks Nirav Kotecha for your answer.
I ended up using CrytoSwift and Add Extension class NSString and String to call it.
Related
Java code is done to generate 3DES result, segment code as below:
Cipher cipher = Cipher.getInstance("DESede/ECB/NoPadding");
cipher.init(Cipher.ENCRYPT_MODE, key);
byte[] result = cipher.doFinal(data);
Now, I need to implement same result in objective-C, below is my try, but the result is not even close.
+(NSString *) try3DES:(NSString *)plainText key:(NSString *)key
{
NSString *ciphertext = nil;
NSData *textData = [plainText dataUsingEncoding:NSUTF8StringEncoding];
NSUInteger dataLength = [textData length];
unsigned char buffer[1024];
memset(buffer, 0, sizeof(char));
size_t numBytesEncrypted = 0;
CCCryptorStatus cryptStatus = CCCrypt(kCCEncrypt,
kCCAlgorithmDES,
kCCOptionPKCS7Padding,
[key UTF8String],
kCCKeySizeDES,
nil,
[textData bytes],
dataLength,
buffer,
1024,
&numBytesEncrypted);
if (cryptStatus == kCCSuccess) {
NSData *data = [NSData dataWithBytes:buffer length:(NSUInteger)numBytesEncrypted];
ciphertext = [self convertDataToHexStr:data];
}
return ciphertext;
}
Could anybody can help?
I am trying to encrypt a string with 'AES-128 CBC with IV'. Here is the input parameter and expected output:
Key:
000102030405060708090A0B0C0D0E0F
IV:
00102030405060708090A0B0C0D0E0F0
Input data:
EA010B23CDA9B16F0001020304050607
Output:
B773C36749E87D3F8FED98FE52026A15
I have verified the output on this web site:
http://extranet.cryptomathic.com/aescalc/index?key=000102030405060708090A0B0C0D0E0F&iv=00102030405060708090A0B0C0D0E0F0&input=EA010B23CDA9B16F0001020304050607&mode=cbc&action=Encrypt&output=B773C36749E87D3F8FED98FE52026A15
How to encrypt a string with AES-128 CBC with IV in objective C? (With same result as http://extranet.cryptomathic.com/aescalc) I am trying to get the encrypted string - B773C36749E87D3F8FED98FE52026A15 , but no luck.
I have tried to use this library for the encryption: https://github.com/Pakhee/Cross-platform-AES-encryption/tree/master/iOS
Here is my objective c code:
NSString* data = #"EA010B23CDA9B16F0001020304050607";
NSString* key = #"000102030405060708090A0B0C0D0E0F";
NSString* iv = #"00102030405060708090A0B0C0D0E0F0";
NSData *encryptedData = [[StringEncryption alloc] encrypt:[#"EA010B23CDA9B16F0001020304050607" dataUsingEncoding:NSUTF8StringEncoding] key:key iv:iv];
NSLog(#"encryptedData %#", encryptedData);
The output of encryptedData is:
<68f8ed75 e79f2ba2 c80e67a2 f0c84b7a c4b07fd1 59e937e5 14644cba c0ddb60c 40502375 7798e7a1 58bd05a5 b3d9e7bd>
I expect the value of *encryptedData should be <42373733 43333637 34394538 37443346 38464544 39384645 35323032 36413135>, which is hex of B773C36749E87D3F8FED98FE52026A15
I have tried another library - https://github.com/dev5tec/FBEncryptor
NSData* _data = [data dataUsingEncoding:NSUTF8StringEncoding];
NSData* _key = [key dataUsingEncoding:NSUTF8StringEncoding];
NSData* _iv = [iv dataUsingEncoding:NSUTF8StringEncoding];
NSData *encryptedData2 = [FBEncryptorAES encryptData:_data key:_key iv:_iv];
NSLog(#"encryptedData2 = %#", encryptedData2);
Output is <2beea977 aef69eb1 ed9f6dd0 7bf5f1ce d1e5df46 2cbf8465 773f122d 03267abb 2e113d9b 07189268 4fd6babe 7b1c0056>
It seems that I am using wrong library or I have wrong input to the encryption function. Any recommendation of AES library for objective c?
Common Crypto is the correct thing to use for encryption for iOS and OSX. The issue it to provide the correct input.
The input key, iv and data appear to be in hexadecimal. Cryptomathic expects it inputs to be in hexadecimal and it's output is in hexadecimal so it works correctly.
But the ObjC code uses:
NSString* data = #"EA010B23CDA9B16F0001020304050607";
NSData* _data = [data dataUsingEncoding:NSUTF8StringEncoding];
which uses the hexadecimal as a character string.
Instead use a hex to data conversion such as #Larme linked to, see the first comment.
From the sizes of the input and output it appears you are using PKCS#7 padding which adds a full block of padding if the input is an exact multiple of the block size, Cryptomathic does not add PKCS#7 padding.
Update
#interface Crypt : NSObject
+ (NSData *)aes128Data:(NSData *)dataIn;
+ (NSData *)dataFromHexString:(NSString *)hexString;
#end
#implementation Crypt
+ (NSData *)aes128Data:(NSData *)dataIn
operation:(CCOperation)operation // kCC Encrypt, Decrypt
key:(NSData *)key
options:(CCOptions)options // kCCOption PKCS7Padding, ECBMode,
iv:(NSData *)iv
error:(NSError **)error
{
CCCryptorStatus ccStatus = kCCSuccess;
size_t cryptBytes = 0;
NSMutableData *dataOut = [NSMutableData dataWithLength:dataIn.length + kCCBlockSizeAES128];
ccStatus = CCCrypt( operation,
kCCAlgorithmAES,
options,
key.bytes, key.length,
iv.bytes,
dataIn.bytes, dataIn.length,
dataOut.mutableBytes, dataOut.length,
&cryptBytes);
if (ccStatus == kCCSuccess) {
dataOut.length = cryptBytes;
}
else {
if (error) {
*error = [NSError errorWithDomain:#"kEncryptionError"
code:ccStatus
userInfo:nil];
}
dataOut = nil;
}
return dataOut;
}
+ (NSData *)dataFromHexString:(NSString *)hexString {
char buf[3];
buf[2] = '\0';
unsigned char *bytes = malloc([hexString length]/2);
unsigned char *bp = bytes;
for (CFIndex i = 0; i < [hexString length]; i += 2) {
buf[0] = [hexString characterAtIndex:i];
buf[1] = [hexString characterAtIndex:i+1];
char *b2 = NULL;
*bp++ = strtol(buf, &b2, 16);
}
return [NSData dataWithBytesNoCopy:bytes length:[hexString length]/2 freeWhenDone:YES];
}
#end
NSString *dataHexString = #"EA010B23CDA9B16F0001020304050607";
NSString *keyHexString = #"000102030405060708090A0B0C0D0E0F";
NSString *ivHexString = #"00102030405060708090A0B0C0D0E0F0";
NSLog(#"dataHexString: %#", dataHexString);
NSLog(#"keyHexString: %#", keyHexString);
NSLog(#"ivHexString: %#", ivHexString);
NSData *data = [Crypt dataFromHexString:dataHexString];
NSData *key = [Crypt dataFromHexString:keyHexString];
NSData *iv = [Crypt dataFromHexString:ivHexString];
NSLog(#"data: %#", data);
NSLog(#"key: %#", key);
NSLog(#"iv: %#", iv);
NSError *error;
NSData *encryptedData = [Crypt
aes128Data:data
operation:kCCEncrypt
key:key
options:0
iv:iv
error:&error];
NSLog(#"encryptedData %#", encryptedData);
Output:
dataHexString: EA010B23CDA9B16F0001020304050607
keyHexString: 000102030405060708090A0B0C0D0E0F
ivHexString: 00102030405060708090A0B0C0D0E0F0
data: <ea010b23 cda9b16f 00010203 04050607>
key: <00010203 04050607 08090a0b 0c0d0e0f>
iv: <00102030 40506070 8090a0b0 c0d0e0f0>
encryptedData: <b773c367 49e87d3f 8fed98fe 52026a15>
Note encryptedData matches the Cryptomathic result.
I am new with iOS7 development and objective c, and i need to develop an application which will send encrypted data with 3DES to a server,I have searched in stack overflow and Net but still unable to get it work, finally i tried this code but i got null as result,
+ (NSString*)encrypt:(NSString*)plainText withKey:(NSString*)key{
uint8_t keyByte[kSecrectKeyLength];
NSMutableData *keyData = [[NSMutableData alloc] init];
int i;
for (i=0; i < [key length] / 2; i++) {
NSString *tempNumber = [key substringWithRange: NSMakeRange(i * 2, 2)];
NSScanner *scanner=[NSScanner scannerWithString:tempNumber];
unsigned int temp;
[scanner scanHexInt:&temp];
Byte B = (Byte)(0xFF & temp);
keyByte[i] = B;
}
NSData* data = [plainText dataUsingEncoding:NSUTF8StringEncoding];
size_t plainTextBufferSize = [data length];
const void *vplainText = (const void *)[data bytes];
CCCryptorStatus ccStatus;
uint8_t *bufferPtr = NULL;
size_t bufferPtrSize = 0;
size_t movedBytes = 0;
bufferPtrSize = (plainTextBufferSize + kCCBlockSize3DES) & ~(kCCBlockSize3DES - 1);
bufferPtr = malloc( bufferPtrSize * sizeof(uint8_t));
memset((void *)bufferPtr, 0x0, bufferPtrSize);
const void *vkey = (const void *) keyByte;
const void *vinitVec = (const void *) [gIv UTF8String];
ccStatus = CCCrypt(kCCEncrypt,
kCCAlgorithm3DES,
kCCOptionPKCS7Padding,
vkey,
kCCKeySize3DES,
vinitVec,
vplainText,
plainTextBufferSize,
(void *)bufferPtr,
bufferPtrSize,
&movedBytes);
NSData *myData = [NSData dataWithBytes:(const void *)bufferPtr length:(NSUInteger)movedBytes];
//NSString *result = [GTMBase64 stringByEncodingData:myData];
NSString *result = [[NSString alloc] initWithData:myData encoding:NSUTF8StringEncoding];
NSLog(#"result=%#",result);
return result;
}
Please have u any idea about the solution???
lol i just struggled with this myself the other day, i have a working solution now using this code
+ (NSData *)tripleDesEncryptString:(NSString *)input
key:(NSString *)key
error:(NSError **)error
{
NSParameterAssert(input);
NSParameterAssert(key);
NSData *inputData = [input dataUsingEncoding:NSUTF8StringEncoding];
NSData *keyData = [key dataUsingEncoding:NSUTF8StringEncoding];
size_t outLength;
NSAssert(keyData.length == kCCKeySize3DES, #"the keyData is an invalid size");
NSMutableData *outputData = [NSMutableData dataWithLength:(inputData.length + kCCBlockSize3DES)];
CCCryptorStatus
result = CCCrypt(kCCEncrypt, // operation
kCCAlgorithm3DES, // Algorithm
kCCOptionPKCS7Padding | kCCOptionECBMode, // options
keyData.bytes, // key
keyData.length, // keylength
nil,// iv
inputData.bytes, // dataIn
inputData.length, // dataInLength,
outputData.mutableBytes, // dataOut
outputData.length, // dataOutAvailable
&outLength); // dataOutMoved
if (result != kCCSuccess) {
if (error != NULL) {
*error = [NSError errorWithDomain:#"com.your_domain.your_project_name.your_class_name."
code:result
userInfo:nil];
}
return nil;
}
[outputData setLength:outLength];
return outputData;
}
+ (NSString *)tripleDesDecryptData:(NSData *)input
key:(NSString *)key
error:(NSError **)error
{
NSParameterAssert(input);
NSParameterAssert(key);
NSData *inputData = input;
NSData *keyData = [key dataUsingEncoding:NSUTF8StringEncoding];
size_t outLength;
NSAssert(keyData.length == kCCKeySize3DES, #"the keyData is an invalid size");
NSMutableData *outputData = [NSMutableData dataWithLength:(inputData.length + kCCBlockSize3DES)];
CCCryptorStatus
result = CCCrypt(kCCDecrypt, // operation
kCCAlgorithm3DES, // Algorithm
kCCOptionPKCS7Padding | kCCOptionECBMode, // options
keyData.bytes, // key
keyData.length, // keylength
nil,// iv
inputData.bytes, // dataIn
inputData.length, // dataInLength,
outputData.mutableBytes, // dataOut
outputData.length, // dataOutAvailable
&outLength); // dataOutMoved
if (result != kCCSuccess) {
if (error != NULL) {
*error = [NSError errorWithDomain:#"com.your_domain.your_project_name.your_class_name."
code:result
userInfo:nil];
}
return nil;
}
[outputData setLength:outLength];
return [[NSString alloc] initWithData:outputData encoding:NSUTF8StringEncoding];
}
you probably want to base64 encode the data the comes out of the encryption method, and then un-base64 anything that you want to decrypt as well, there are built in methods for NSData to do this now, eg:
[data base64EncodedDataWithOptions:(NSDataBase64EncodingOptions)];
to test if the functions work, i used this test function
+ (void) testEncryptionAndDecryption {
NSData *encrypted = [self tripleDesEncryptString:#"test" key:#"123456789123456789123456" error:nil];
NSLog(#"encrypted data length: %lu", (unsigned long)encrypted.length);
NSString *decrypted = [self tripleDesDecryptData:encrypted key:#"123456789123456789123456" error:nil];
NSLog(#"decrypted text: %#", decrypted);
}
this gave me the correct output that you would expect
I have no idea why the (char *)uint8_t array transform to NSString doesn't work.
ivString always is (null)
- (IBAction)encryptPacketBtnTouchDown:(id)sender {
NSString *key = #"1234567890123456";
NSData *plain = [plainMessage.text dataUsingEncoding:NSUTF8StringEncoding];
uint8_t initialisationVector[16];
arc4random_buf(initialisationVector, 16);
NSString* ivString = [NSString stringWithUTF8String:(char *)initialisationVector];
NSData *cipherData = [plain AES128EncryptWithKey:key iv:ivString];
[asyncSocket writeData:cipherData withTimeout:-1.0 tag:0];
NSString* cipherString = [[NSString alloc] initWithBytes:[cipherData bytes]
length:[cipherData length]
encoding:NSASCIIStringEncoding];
}
cipherData NSData * 0x1edaf3a0 16 bytes
cipherString NSString * 0x00000000
initialisationVector uint8_t [16]
ivString NSString * 0x00000000
key NSString * 0x000d28c4 #"1234567890123456"
plain NSData * 0x1ed80760 9 bytes
P.S.
NSString* ivString = [[NSString alloc] initWithBytes:initialisationVector
length:16
encoding:NSUTF8StringEncoding];
This also won't works. Still got (null)
The method I am calling is :
- (NSData *)AES128Operation:(CCOperation)operation key:(NSString *)key iv:(NSString *)iv
{
char keyPtr[kCCKeySizeAES128 + 1];
memset(keyPtr, 0, sizeof(keyPtr));
[key getCString:keyPtr maxLength:sizeof(keyPtr) encoding:NSUTF8StringEncoding];
char ivPtr[kCCBlockSizeAES128 + 1];
memset(ivPtr, 0, sizeof(ivPtr));
[iv getCString:ivPtr
maxLength:sizeof(ivPtr)
encoding:NSUTF8StringEncoding];
NSUInteger dataLength = [self length];
size_t bufferSize = dataLength + kCCBlockSizeAES128;
void *buffer = malloc(bufferSize);
size_t numBytesCrypted = 0;
CCCryptorStatus cryptStatus = CCCrypt(operation,
kCCAlgorithmAES128,
kCCOptionPKCS7Padding,
keyPtr,
kCCBlockSizeAES128,
ivPtr,
[self bytes],
dataLength,
buffer,
bufferSize,
&numBytesCrypted);
if (cryptStatus == kCCSuccess) {
return [NSData dataWithBytesNoCopy:buffer length:numBytesCrypted];
}
free(buffer);
return nil;
}
- (NSData *)AES128EncryptWithKey:(NSString *)key iv:(NSString *)iv
{
return [self AES128Operation:kCCEncrypt key:key iv:iv];
}
Finally, I got the answer!
I just need treat the uint8_t[] array as a char[] array. Then, transform the char[] array to NSString by below line:
NSString* ivString = [NSString stringWithCString:initialisationVector encoding:NSASCIIStringEncoding];
Result is:
ivString NSString * 0x1d8489c0 #"¹U ¡hÌTÖÆáβÍ"
I'm working with a partner and we're not able to get C# and Objective-C to produce the same hashes using what we think are the same tools in the respective languages. In C#, I'm doing this:
byte[] noncebytes=new byte[32];
//We seed the hash generator with a new 32 position array. Each position is 0.
//In prod code this would be random, but for now it's all 0s.
HMACSHA256 hmac256 = new HMACSHA256(noncebytes);
string plaintext = "hello";
string UTFString = Convert.ToBase64String(
System.Text.Encoding.UTF8.GetBytes(plaintext));
string HashString = Convert.ToBase64String(
hmac256.ComputeHash(System.Text.Encoding.UTF8.GetBytes(plaintext))); //Convert that hash to a string.
This produces the following base64string hash:
Q1KybjP+DXaaiSKmuikAQQnwFojiasyebLNH5aWvxNo=
What is the equivalent Objective-C code to do this? We need the client and the server to be able to generate matching hashes for matching data.
Here is the Objective-C code we are currently using:
...
NSData *zeroNumber = [self zeroDataWithBytes:32]; //empty byte array
NSString *nonceTest = [zeroNumber base64String]; // using MF_Base64Additions.h here
NSData *hashTest = [self hmacForKeyAndData:nonceTest withData:#"hello"]; //creating hash
NSString *hashTestText = [hashTest base64String];
NSLog(#"hello hash is %#", hashTestText);
...
//functions for zeroing out the byte. I'm sure there's a better way
- (NSData *)zeroDataWithBytes: (NSUInteger)length {
NSMutableData *mutableData = [NSMutableData dataWithCapacity: length];
for (unsigned int i = 0; i < length; i++) {
NSInteger bits = 0;
[mutableData appendBytes: (void *) &bits length: 1];
} return mutableData;
}
//hash function
-(NSData *) hmacForKeyAndData:(NSString *)key withData:(NSString *) data {
const char *cKey = [key cStringUsingEncoding:NSASCIIStringEncoding];
const char *cData = [data cStringUsingEncoding:NSASCIIStringEncoding];
unsigned char cHMAC[CC_SHA256_DIGEST_LENGTH];
CCHmac(kCCHmacAlgSHA256, cKey, strlen(cKey), cData, strlen(cData), cHMAC);
return [[NSData alloc] initWithBytes:cHMAC length:sizeof(cHMAC)];
}
UPDATE:
There is a pretty good project on GitHub that seems to accomplish everything you want, plus a lot more encryption related options; includes unit tests.
NSData *hmacForKeyAndData(NSString *key, NSString *data)
{
const char *cKey = [key cStringUsingEncoding:NSASCIIStringEncoding];
const char *cData = [data cStringUsingEncoding:NSASCIIStringEncoding];
unsigned char cHMAC[CC_SHA256_DIGEST_LENGTH];
CCHmac(kCCHmacAlgSHA256, cKey, strlen(cKey), cData, strlen(cData), cHMAC);
return [[NSData alloc] initWithBytes:cHMAC length:sizeof(cHMAC)];
}
(Source)
With the above, I think you will have import <CommonCrypto/CommonHMAC.h>. The next step for encoding to Base64:
+ (NSString *)Base64Encode:(NSData *)data
{
//Point to start of the data and set buffer sizes
int inLength = [data length];
int outLength = ((((inLength * 4)/3)/4)*4) + (((inLength * 4)/3)%4 ? 4 : 0);
const char *inputBuffer = [data bytes];
char *outputBuffer = malloc(outLength);
outputBuffer[outLength] = 0;
//64 digit code
static char Encode[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
//start the count
int cycle = 0;
int inpos = 0;
int outpos = 0;
char temp;
//Pad the last to bytes, the outbuffer must always be a multiple of 4
outputBuffer[outLength-1] = '=';
outputBuffer[outLength-2] = '=';
/* http://en.wikipedia.org/wiki/Base64
Text content M a n
ASCII 77 97 110
8 Bit pattern 01001101 01100001 01101110
6 Bit pattern 010011 010110 000101 101110
Index 19 22 5 46
Base64-encoded T W F u
*/
while (inpos < inLength){
switch (cycle) {
case 0:
outputBuffer[outpos++] = Encode[(inputBuffer[inpos]&0xFC)>>2];
cycle = 1;
break;
case 1:
temp = (inputBuffer[inpos++]&0x03)<<4;
outputBuffer[outpos] = Encode[temp];
cycle = 2;
break;
case 2:
outputBuffer[outpos++] = Encode[temp|(inputBuffer[inpos]&0xF0)>> 4];
temp = (inputBuffer[inpos++]&0x0F)<<2;
outputBuffer[outpos] = Encode[temp];
cycle = 3;
break;
case 3:
outputBuffer[outpos++] = Encode[temp|(inputBuffer[inpos]&0xC0)>>6];
cycle = 4;
break;
case 4:
outputBuffer[outpos++] = Encode[inputBuffer[inpos++]&0x3f];
cycle = 0;
break;
default:
cycle = 0;
break;
}
}
NSString *pictemp = [NSString stringWithUTF8String:outputBuffer];
free(outputBuffer);
return pictemp;
}
Note the second line of code in the objective-c portion of the question.
NSString *nonceTest = [zeroNumber base64String];
but it should be this:
NSString *nonceTest = [[NSString alloc] initWithData:zeroNumber encoding:NSASCIIStringEncoding];
It was a case of converting the string to base64 when we didn't need to for the hmac seeeding.
We now get: Q1KybjP+DXaaiSKmuikAQQnwFojiasyebLNH5aWvxNo= as the hash on both platforms.