How to convert audio float array to short array() ?
Here is how to encode and decode a float with NSData:
encoding:
NSMutableData * data = [NSMutableData dataWithCapacity:0];
float z = ...;
[data appendBytes:&z length:sizeof(float)];
decoding:
NSData * data = ...; // loaded from bluetooth
float z;
[data getBytes:&z length:sizeof(float)];
A couple of things to note here:
You have to use NSMutableData if you are going to add things to the data object after creating it. The other option is to simply load the data all in one shot:
NSData * data = [NSData dataWithBytes:&z length:sizeof(float)];
the getBytes:length: method is for retrieving bytes from an NSData object, not for copying bytes into it.
Related
I have an encryption function that gets data and key, with inner iv and returns an encrypted string. I can encrypt every string that contains just English characters but not about Arabic. This is my function. Please help me to find the problem. Thanks
-(NSString*)Encrypt:(NSString*)data second:(NSString*)key
{
size_t outLength;
NSMutableData * cipherData = [NSMutableData dataWithLength:data.length + kCCBlockSizeAES128];
Byte byte[] = {1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,}; //It`s not valid. The main iv is secret
NSData *datakey = [NSData dataWithBytes:key.UTF8String length:key.length];
NSData *datadata = [NSData dataWithBytes:data.UTF8String length:data.length];
CCCryptorStatus result = CCCrypt( kCCEncrypt
, kCCAlgorithmAES128
, kCCOptionPKCS7Padding
, datakey.bytes
, [datakey length]
, byte
, datadata.bytes
, [datadata length]
, cipherData.mutableBytes
, cipherData.length
, &outLength);
if (result == kCCSuccess) {
cipherData.length = outLength;
}
else {
}
NSData *encryptedData=cipherData;
NSString *str=[encryptedData base64EncodedStringWithOptions: NSDataBase64Encoding64CharacterLineLength];
return str;
}
The problem is that cipherData is to short. It need to be a block longer than datadata which may (such as in this case) be longer than data.length.
When creating data with utf-8 encoding from a string that contains multiple-byte data such as Arabic, emoji and etc the data will be longer than the string characters.
Incorrect code:
NSMutableData * cipherData = [NSMutableData dataWithLength:data.length + kCCBlockSizeAES128];
NSData *datadata = [NSData dataWithBytes:data.UTF8String length:data.length];
Correct code:
NSData *datadata = [data dataUsingEncoding:NSUTF8StringEncoding];
NSMutableData * cipherData = [NSMutableData dataWithLength: datadata.length + kCCBlockSizeAES128];
Note that misnaming the input string data does not help, it is a string. renaming data -> tex and then ``datadata->data` makes the code more clear. Good naming solves many code problems.
I have two Apps now, one of those convert the CMSampleBuffer video data to NSData object, then transport it via network.Another App receive those data, now how can I convert NSData object back to CMSampleBuffer data?
Here is a way I use it to convert CMSampleBuffer to NSData object:
CMBlockBufferRef blockBufferRef = CMSampleBufferGetDataBuffer(sampleBuffer);
size_t length = CMBlockBufferGetDataLength(blockBufferRef);
Byte buffer[length];
CMBlockBufferCopyDataBytes(blockBufferRef, 0, length, buffer);
NSData *data = [NSData dataWithBytes:buffer length:length];
Or I just need another way to transport the video data?
I think this generates random 64 bytes NSData.
uint8_t buffer[64];
SecRandomCopyBytes(kSecRandomDefault, 64, buffer);
NSData *keyData = [[NSData alloc] initWithBytes:buffer length:sizeof(buffer)];
I want to generate 64 bytes NSData like this but not a random data.
How can I generate 64 bytes NSData with a given key like "com.this.is.akey".
Tried this one but it gave me wrong bytes size(not 64 bytes).
NSString *base64EncodedString = [[#"somekey.here" dataUsingEncoding:NSUTF8StringEncoding] base64EncodedStringWithOptions:0];
NSData *encodedData = [[NSData alloc] initWithBase64EncodedString:base64EncodedString
options:0];
You can use -[NSString dataUsingEncoding:] to convert NSString to NSData.
NSString *key = #"com.this.is.akey";
NSData *keyData = [key dataUsingEncoding:NSASCIIStringEncoding];
If length of the data is less or greater than 64 bytes, you should pad or truncate data to exact 64 bytes.
if (keyData.length != 64) {
NSMutableData *mutableData = keyData.mutableCopy;
mutableData.length = 64;
keyData = mutableData.copy;
}
Then, you can pass the NSData object to RLMRealmConfiguration.encryptionKey.
RLMRealmConfiguration *config = [RLMRealmConfiguration defaultConfiguration];
config.encryptionKey = keyData;
NSError *error = nil;
RLMRealm *realm = [RLMRealm realmWithConfiguration:config error:&error];
Given a string for a key one should use a key derivation function such as PBKDF2.
Example:
#import <CommonCrypto/CommonCrypto.h>
NSString *keyString = #"com.this.is.key"; // Should use a random value
NSData *keyData = [keyString dataUsingEncoding:NSUTF8StringEncoding];
NSData *salt = [#"saltstring" dataUsingEncoding:NSUTF8StringEncoding];
NSMutableData *derivedKey = [NSMutableData dataWithLength:CC_SHA512_DIGEST_LENGTH];
CCKeyDerivationPBKDF(kCCPBKDF2,
keyData.bytes, keyData.length,
salt.bytes, salt.length,
kCCPRFHmacAlgSHA512,
10000, // Choose for desired timing
derivedKey.mutableBytes, derivedKey.length);
NSLog(#"derivedKey: %#", derivedKey);
Output: derivedKey:
065d2106 1da7ebcf d155a50a b1ee5540 dee8efce f4678c47 02164488 e92e05e5 30c1f12d a3813013 652aca1b 0016b258 610d7929 f240de72 3eab85d9 7e028b35
Notes:
It is best to set the salt to a random value and provide it along with the derived key.
The iteration count should set to provide a suitable derivation tine, perhaps 100ms. There is a corresponding CCCalibratePBKDF function the help with this. The iteration count can also be provided along with the derived key.
Sorry if this seems to be more work that necessary but security is not easy to get right.
I am using the following code to write the 0xDE value for a Bluetooth Caracteristic (Reset Device) using the IOS Core Bluetooth :
...
NSData *bytes = [#"0xDE" dataUsingEncoding:NSUTF8StringEncoding];
[peripheral writeValue:bytes
forCharacteristic:characteristic
type:CBCharacteristicWriteWithResponse];
...
is there any mistake in my code because the value is not written properly?
Swift 3.0: In case anyone is wondering the format for Swift is slightly different as writeValue can get the count from the array.
let value: UInt8 = 0xDE
let data = Data(bytes: [value])
peripheral.writeValue(data, for: characteristic, type: .withResponse)
Try creating your data with an array of single byte values.
const uint8_t bytes[] = {0xDE};
NSData *data = [NSData dataWithBytes:bytes length:sizeof(bytes)];
This is a useful approach for creating arbitrary constant data. For more bytes,
const uint8_t bytes[] = {0x01,0x02,0x03,0x04,0x05};
NSData *data = [NSData dataWithBytes:bytes length:sizeof(bytes)];
If you want to create data to send using variables, I would recommend using NSMutableData and appending the bytes that you need. It isn't very pretty, but it is easy to read / understand, especially when you are matching a packed struct on the embedded side. Example below is from a BLE project where we were making a simple communication protocol.
NSMutableData *data = [[NSMutableData alloc] init];
//pull out each of the fields in order to correctly
//serialize into a correctly ordered byte stream
const uint8_t start = PKT_START_BYTE;
const uint8_t bitfield = (uint8_t)self.bitfield;
const uint8_t frame = (uint8_t)self.frameNumber;
const uint8_t size = (uint8_t)self.size;
//append the individual bytes to the data chunk
[data appendBytes:&start length:1];
[data appendBytes:&bitfield length:1];
[data appendBytes:&frame length:1];
[data appendBytes:&size length:1];
The answer by bensarz is almost correct. Except one thing: you shouldn't use sizeof(int) as the length for NSData. The size of int is 4 or 8 bytes (depending on the architecture). As you want to send 1 byte, use uint8_t or Byte instead:
uint8_t byteToWrite = 0xDE;
NSData *data = [[NSData alloc] initWithBytes:&byteToWrite length:sizeof(&byteToWrite)];
[peripheral writeValue:data
forCharacteristic:characteristic
type:CBCharacteristicWriteWithResponse];
Of courser you could also use int as the variable's type, but you have to initialize NSData with the length of 1.
This code will fix the problem :
NSData * data = [self dataWithHexString: #"DE"];
[peripheral writeValue:data forCharacteristic:characteristic
type:CBCharacteristicWriteWithResponse];
dataWithHexString implementation :
- (NSData *)dataWithHexString:(NSString *)hexstring
{
NSMutableData* data = [NSMutableData data];
int idx;
for (idx = 0; idx+2 <= hexstring.length; idx+=2) {
NSRange range = NSMakeRange(idx, 2);
NSString* hexStr = [hexstring substringWithRange:range];
NSScanner* scanner = [NSScanner scannerWithString:hexStr];
unsigned int intValue;
[scanner scanHexInt:&intValue];
[data appendBytes:&intValue length:1];
}
return data;
}
What you are, in fact, doing here is writing the string "0xDE" to the characteristic. If you want to use binary/octal notation, you need to stay away from strings.
int integer = 0xDE;
NSData *data = [[NSData alloc] initWithBytes:&integer length:sizeof(integer)];
[peripheral writeValue:data
forCharacteristic:characteristic
type:CBCharacteristicWriteWithResponse];
How do I convert a series of 32 bits (representing 4 bytes) stored in an NSString, into an NSData object of 4 bytes in objective-c?
For example, how can I convert the following string:
NSString *bitSeries = #"00000000000000000000000111101100";
into NSData object with length precisely 4?
You can use strtoul() with base 2 to convert the string to an unsigned integer:
NSString *bitSeries = #"00000000000000000000000111101100";
uint32_t value = strtoul([bitSeries UTF8String], NULL, 2);
and then create an NSData object:
NSData *data = [NSData dataWithBytes:&value length:sizeof(value)];
NSLog(#"%#", data);
// Output: <ec010000>
Or, if you prefer big-endian byte order:
value = OSSwapHostToBigInt32(value);
NSData *data = [NSData dataWithBytes:&value length:sizeof(value)];
NSLog(#"%#", data);
// Output: <000001ec>