I have defined a GUID structure as below
typedef struct _GUID {
unsigned long Data1;
unsigned short Data2;
unsigned short Data3;
unsigned char Data4[ 8 ];
} GUID;
I’m trying to convert it to NSString. However, I’m getting the reversed values for the first three (long, short,short). It may be due to the Big-endian.
Example:
GUID testGUID = { 0x865f82d0, 0x3303, 0x403d, { 0xbf, 0xcd, 0xeb, 0xb2, 0xde, 0xd9, 0xa0, 0x69 } };
NSUUID *uuid = [[NSUUID alloc] initWithUUIDBytes:(const unsigned char*)&testGUID];
NSString *uuidString = [uuid UUIDString];
NSLog(#"%#", uuidString);
Output: D0825F86-0333-3D40-BFCD-EBB2DED9A069
Expected: 865F82D0-3303-403D-BFCD-EBB2DED9A069
let me know Is there a way to correct this. Any help on this is much appreciated.
#borrrden comment fixed the issue.
Here is the solution.
GUID testGUID = { 0x865f82d0, 0x3303, 0x403d, { 0xbf, 0xcd, 0xeb, 0xb2, 0xde, 0xd9, 0xa0, 0x69 } };
testGUID.Data1 = NTOHL(testGUID.Data1);
testGUID.Data2 = NTOHS(testGUID.Data2);
testGUID.Data3 = NTOHS(testGUID.Data3);
NSUUID *uuid = [[NSUUID alloc] initWithUUIDBytes:(const unsigned char*)&testGUID];
NSString *uuidString = [uuid UUIDString];
NSLog(#"%#", uuidString)
Related
I convert NSString to byte Array. It ok, then I convert NSData to base64 is wrong. if "010203040506" is right but with high number (exam: #"333435363738") is wrong. This is my code. Please help me.
In Android: ISIjJCUm and iOS: MzQ1Njc4.
NSString *command = #"333435363738";
NSMutableData *commandToSend= [[NSMutableData alloc] init];
unsigned long whole_byte;
char byte_chars[3] = {'\0','\0','\0'};
int i;
for (i=0; i < [command length] /2; i++) {
NSLog(#"%d",[command characterAtIndex:i*2]);
NSLog(#"%d",[command characterAtIndex:i*2 + 1]);
byte_chars[0] = [command characterAtIndex:i*2];
byte_chars[1] = [command characterAtIndex:i*2 + 1];
whole_byte = strtol(byte_chars, NULL, 16);
[commandToSend appendBytes:&whole_byte length:1];
}
NSString *base64String;
if ([commandToSend respondsToSelector:#selector(base64EncodedStringWithOptions:)]) {
base64String = [commandToSend base64EncodedStringWithOptions:kNilOptions]; // iOS 7+
} else {
base64String = [commandToSend base64Encoding]; // pre iOS7
}
Your code produces the string MzQ1Njc4 which is the bas64 encoding of the bytes 0x33, 0x34, 0x35, 0x36, 0x37, 0x38. This appears to be what the code is meant to do.
The string ISIjJCUm is the base64 encoding of 0x21, 0x22, 0x23, 0x24, 0x25, 0x26.
Note that 0x21 is 33 decimal. So it looks like you were either meant to interpret the string as decimal on iOS or as hex on Android.
How do you convert from NSString to UInt64?
For example, something like this if a UInt64Value helper method existed:
NSString *value = #"1234567";
UInt64 convertedValue = [value UInt64Value];
I am trying to do this in an iOS project.
To pitch another possibility for completeness:
NSScanner *scanner = [NSScanner scannerWithString:value];
unsigned long long convertedValue = 0;
[scanner scanUnsignedLongLong:&convertedValue];
return convertedValue;
... check the result on scanUnsignedLongLong if you want to differentiate between finding a value of 0 and finding something that isn't a number.
NSString * num = #"123456";
NSNumberFormatter * numberFormatter = [[NSNumberFormatter alloc]init];
NSNumber * number = [numberFormatter numberFromString:num];
unsigned long long valueUInt64 = number.unsignedLongLongValue;
You can use strtoull(const char *, char **, int) as following:
NSString *value = #"1234567";
UInt64 convertedValue = strtoull([value UTF8String], NULL, 0);
You can get a UInt64 with longLongValue
NSString *str = #"23147653105732";
UInt64 uint64 = [str longLongValue];
Another way to get an int64 is:
NSString *str = #"23147653105732";
int64_t int64_t = atoll([str UTF8String]);
When I NSLog characteristic.value it shows as either <1100> or <2200>. I know this is a hexadecimal. I'm confused as what to write when I'm changing the value.
Any help would be much appreciated.
At the moment I'm doing the following, but getting null when I change the values.
- (IBAction)deviceSwitchPressed:(id)sender {
if ([sender isOn]) {
[activePeripheral writeValue:[#"1100" dataUsingEncoding:NSUTF8StringEncoding] forCharacteristic:switchCharacterictic type:CBCharacteristicWriteWithResponse];
} else {
[activePeripheral writeValue:[#"2200" dataUsingEncoding:NSUTF8StringEncoding] forCharacteristic:switchCharacterictic type:CBCharacteristicWriteWithResponse];
}
NSLog(#"characteristic.value = %#", switchCharacterictic.value);
}
This is what I use to convert hex string values into data objects.
NSString *command = hexString;
command = [command stringByReplacingOccurrencesOfString:#" " withString:#""];
NSMutableData *commandToSend= [[NSMutableData alloc] init];
unsigned char whole_byte;
char byte_chars[3] = {'\0','\0','\0'};
int i;
for (i=0; i < [command length]/2; i++) {
byte_chars[0] = [command characterAtIndex:i*2];
byte_chars[1] = [command characterAtIndex:i*2+1];
whole_byte = strtol(byte_chars, NULL, 16);
[commandToSend appendBytes:&whole_byte length:1];
}
However writing a value to a characteristic doesn't guarantee that is what will be returned. The peripheral can handle that data in anyway that it wants.
i have a public key which i gathered from a remote server and i want to perform RSA encryption with that public key. But the problem is i get the public key data as byte array in buffer. I can convert it to NSData but i can not convert to SecKeyRef so i can keep going with encryption. My encryption code is like:
+(NSString *)encryptRSA:(NSString *)plainTextString withKey:(SecKeyRef)publicKey {
size_t cipherBufferSize = SecKeyGetBlockSize(publicKey);
uint8_t *cipherBuffer = malloc(cipherBufferSize);
uint8_t *nonce = (uint8_t *)[plainTextString UTF8String];
SecKeyEncrypt(publicKey,
kSecPaddingOAEP,
nonce,
strlen( (char*)nonce ),
&cipherBuffer[0],
&cipherBufferSize);
NSData *encryptedData = [NSData dataWithBytes:cipherBuffer length:cipherBufferSize];
return [encryptedData base64EncodedStringWithOptions:NSDataBase64Encoding64CharacterLineLength];
}
As you can see i need SecKeyRef object type to complete my encryption. But my RSA public key is in NSData variable. So how can i convert NSData to SecKeyRef object type. Thanks in advance.
Use this function to save your public key. Pass your RAS public key and any name for peername.
- (void)addPeerPublicKey:(NSString *)peerName keyBits:(NSData *)publicKeyData {
OSStatus sanityCheck = noErr;
CFTypeRef persistPeer = NULL;
[self removePeerPublicKey:peerName];
NSData * peerTag = [[NSData alloc] initWithBytes:(const void *)[peerName UTF8String] length:[peerName length]];
NSMutableDictionary * peerPublicKeyAttr = [[NSMutableDictionary alloc] init];
[peerPublicKeyAttr setObject:(id)kSecClassKey forKey:(id)kSecClass];
[peerPublicKeyAttr setObject:(id)kSecAttrKeyTypeRSA forKey:(id)kSecAttrKeyType];
[peerPublicKeyAttr setObject:peerTag forKey:(id)kSecAttrApplicationTag];
[peerPublicKeyAttr setObject:publicKeyData forKey:(id)kSecValueData];
[peerPublicKeyAttr setObject:[NSNumber numberWithBool:YES] forKey:(id)kSecReturnData];
sanityCheck = SecItemAdd((CFDictionaryRef) peerPublicKeyAttr, (CFTypeRef *)&persistPeer);
if(sanityCheck == errSecDuplicateItem){
TRC_DBG(#"Problem adding the peer public key to the keychain, OSStatus == %ld.", sanityCheck );
}
TRC_DBG(#"SecItemAdd OSStATUS = %ld", sanityCheck);
// TRC_DBG(#"PersistPeer privatekey data after import into keychain %#", persistPeer);
persistPeer = NULL;
[peerPublicKeyAttr removeObjectForKey:(id)kSecValueData];
sanityCheck = SecItemCopyMatching((CFDictionaryRef) peerPublicKeyAttr, (CFTypeRef*)&persistPeer);
TRC_DBG(#"SecItemCopying OSStATUS = %ld", sanityCheck);
// TRC_DBG(#"SecItem copy matching returned this public key data %#", persistPeer);
// The nice thing about persistent references is that you can write their value out to disk and
// then use them later. I don't do that here but it certainly can make sense for other situations
// where you don't want to have to keep building up dictionaries of attributes to get a reference.
//
// Also take a look at SecKeyWrapper's methods (CFTypeRef)getPersistentKeyRefWithKeyRef:(SecKeyRef)key
// & (SecKeyRef)getKeyRefWithPersistentKeyRef:(CFTypeRef)persistentRef.
[peerTag release];
[peerPublicKeyAttr release];
if (persistPeer) CFRelease(persistPeer);
}
This is the function to retrieve the public key ref. Pass the same name which one is used for save.
-(SecKeyRef)getPublicKeyReference:(NSString*)peerName{
OSStatus sanityCheck = noErr;
SecKeyRef pubKeyRefData = NULL;
NSData * peerTag = [[NSData alloc] initWithBytes:(const void *)[peerName UTF8String] length:[peerName length]];
NSMutableDictionary * peerPublicKeyAttr = [[NSMutableDictionary alloc] init];
[peerPublicKeyAttr setObject:(id)kSecClassKey forKey:(id)kSecClass];
[peerPublicKeyAttr setObject:(id)kSecAttrKeyTypeRSA forKey:(id)kSecAttrKeyType];
[peerPublicKeyAttr setObject:peerTag forKey:(id)kSecAttrApplicationTag];
[peerPublicKeyAttr setObject:[NSNumber numberWithBool:YES] forKey: (id)kSecReturnRef];
sanityCheck = SecItemCopyMatching((CFDictionaryRef) peerPublicKeyAttr, (CFTypeRef*)&pubKeyRefData);
[peerTag release];
[peerPublicKeyAttr release];
TRC_DBG(#"SecItemCopying OSStATUS = %ld", sanityCheck);
if(pubKeyRefData){
TRC_DBG(#"SecItem copy matching returned this publickeyref %#", pubKeyRefData);
return pubKeyRefData;
}else{
TRC_DBG(#"pubKeyRef is NULL");
return nil;
}
}
Pass your public key data to this function before addPeerPublicKey
- (NSData *)stripPublicKeyHeader:(NSData *)d_key
{
// Skip ASN.1 public key header
if (d_key == nil) return(nil);
unsigned int len = [d_key length];
if (!len) return(nil);
unsigned char *c_key = (unsigned char *)[d_key bytes];
unsigned int idx = 0;
if (c_key[idx++] != 0x30) return(nil);
if (c_key[idx] > 0x80) idx += c_key[idx] - 0x80 + 1;
else idx++;
// PKCS #1 rsaEncryption szOID_RSA_RSA
static unsigned char seqiod[] =
{ 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01,
0x01, 0x05, 0x00 };
if (memcmp(&c_key[idx], seqiod, 15)) return(nil);
idx += 15;
if (c_key[idx++] != 0x03) return(nil);
if (c_key[idx] > 0x80) idx += c_key[idx] - 0x80 + 1;
else idx++;
if (c_key[idx++] != '\0') return(nil);
// Now make a new NSData from this buffer
return([NSData dataWithBytes:&c_key[idx] length:len - idx]);
}
Hope It will work....
-(NSData*)convertIOSKeyToASNFormat:(NSData*)iosKey{
static const unsigned char _encodedRSAEncryptionOID[15] = {
/* Sequence of length 0xd made up of OID followed by NULL */
0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86,
0xf7, 0x0d, 0x01, 0x01, 0x01, 0x05, 0x00
};
// OK - that gives us the "BITSTRING component of a full DER
// encoded RSA public key - we now need to build the rest
unsigned char builder[15];
NSMutableData * encKey = [[[NSMutableData alloc] init] autorelease];
int bitstringEncLength;
// When we get to the bitstring - how will we encode it?
if ([iosKey length ] + 1 < 128 )
bitstringEncLength = 1 ;
else
bitstringEncLength = (([iosKey length ] +1 ) / 256 ) + 2 ;
// Overall we have a sequence of a certain length
builder[0] = 0x30; // ASN.1 encoding representing a SEQUENCE
// Build up overall size made up of -
size_t i = sizeof(_encodedRSAEncryptionOID) + 2 + bitstringEncLength +
[iosKey length];
size_t j = [self encodeLen:&builder[1] length:i];
[encKey appendBytes:builder length:j +1];
// First part of the sequence is the OID
[encKey appendBytes:_encodedRSAEncryptionOID
length:sizeof(_encodedRSAEncryptionOID)];
// Now add the bitstring
builder[0] = 0x03;
j = [self encodeLen:&builder[1] length:[iosKey length] + 1];
builder[j+1] = 0x00;
[encKey appendBytes:builder length:j + 2];
// Now the actual key
[encKey appendData:iosKey];
return encKey;
}
I need to represent a NSInteger and NSString into array of bytes. below are the sample of what I am looking for.
For how, this harcodings are working fine. I want to do this through code. Any clue.
First, NSInteger into bytes of Hex:
NSInteger test = 1;
unsigned char byte[] = { 0x00, 0x01 };
NSInteger test = 16;
unsigned char byte[] = { 0x00, 0x10 };
NSData *data = [NSData dataWithBytes:byte length:sizeof(byte)];
Second, NSString into bytes of Hex:
NSString *test = #"31C5B562-BD07-4616-BCBD-130BA6822790";
unsigned char byte[] = {0x31, 0xC5, 0xB5, 0x62, 0xBD, 0x07, 0x46, 0x16, 0xBC, 0xBD, 0x13, 0x0B, 0xA6, 0x82, 0x27, 0x90};
NSData *data = [NSData dataWithBytes:byte length:sizeof(byte)];
I tried with below code and it works well for my UUID but for NSInteger to to be working I need to send "0010" instead of 16 and "0001" instead of 1. So any clue on how to do this conversion.
- (NSData *)hexData {
NSMutableData *hexData = [NSMutableData data];
int idx = 0;
for (idx = 0; idx+2 <= self.length; idx+=2) {
NSRange range = NSMakeRange(idx, 2);
NSString* hexStr = [self substringWithRange:range];
NSScanner* scanner = [NSScanner scannerWithString:hexStr];
unsigned int intValue;
[scanner scanHexInt:&intValue];
[hexData appendBytes:&intValue length:1];
}
return hexData;
}
EDIT:
int8_t test = -59;
int8_t bytes = CFSwapInt16HostToBig(test);
NSData *data1 = [NSData dataWithBytes:&bytes length:sizeof(bytes)];
Reaching as 0xFF instead of 0xC4
Since your string is a UUID string you can do something like this:
NSString *test = #"";
uuid_t uuid;
uuid_parse([test UTF8String], uuid)
NSData *data = [NSData dataWithBytes:uuid length:16];
For the number you can do:
NSInteger test = 1;
NSData *data = [NSData dataWithBytes:&test length:sizeof(test)];
Keep in mind that NSInteger is probably more than two bytes and you may also need to worry about byte order.
Update: Since it seems you need the integer value to be two bytes, you should do:
uint16_t test = 1;
NSData *data = [NSData dataWithBytes:&test length:sizeof(test)];
This will ensure 2 bytes. You also need to worry about byte ordering so you really need:
uint16_t test = 1;
uint16_t bytes = CFSwapInt16HostToBig(test);
NSData *data = [NSData dataWithBytes:&bytes length:sizeof(bytes)];
Change CFSwapInt16HostToBig to CFSwapInt16HostToLitte if appropriate.