How to read binary QR Code with AVFoundation? - ios

Is it possible to read a binary encoded QR Code with AVFoundation?
I can get a AVMetadataMachineReadableCodeObject object of .type AVMetadataObjectTypeQRCode, however this only has a stringValue property, which won't work, because the data contained in the QR Code can't be converted to a string friendly representation.
Should I use ZXing instead?
Thanks.

The raw data does exist in your AVMetadataMachineReadableCodeObject, but it's not available through a public getter.
However, you can use KVO to extract it, but Apple might reject your app. Also, future iOS versions might change their private APIs and your code could become invalid (because of the hardcoded private keys).
Swift:
readableCodeObject.valueForKeyPath("_internal.basicDescriptor")!["BarcodeRawData"]
Objective-C
[readableCodeObject valueForKeyPath:#"_internal.basicDescriptor"][#"BarcodeRawData"];
I tested this for iOS 8 and 9.

I was able to solve this issue by Base64 encoding the data in the QR code.
This obviously won't work if you're not also generating the QR codes but could be option for people that are.
We were running into the upper limit of data that can be stored in a QR code but by compressing the data (we used zlib) and then Base64 encoding the compressed data, so long as your data compresses to less than 75% of its original size you get some additional capacity and can use the stringValue property to get your data back out, you just have to Base64 decode and then decompress to get the original data back.
Even if you're starting with binary data that isn't very compressible, so long as you can handle the overhead of Base64 and still be within the limitations of QR codes this may be a viable option that avoids working around the fact that AVMetadataMachineReadableCodeObject seems to want to work with string values.

You can use a CIDetector to get to a CIQRCodeFeature which has a symbolDescriptor which has a errorCorrectedPayload which contains the data.
Only problem is that this data still includes QR code headers, like ECI etc... so you still need to interpret the bits.
I summed it up in a post here.

Inspired by previous answers and other sites, I have created a gist that allows to extract binary from QR code or Aztec code, without using private APIs nor other library. It is a AVMetadataMachineReadableCodeObject extension presenting a binaryValue.
However, it only runs on iOS 11 and later, because of the CIQRCodeDescriptor use.
It is available here : https://gist.github.com/PetrusM/267e2ee8c1d8b5dca17eac085afa7d7c
For QR codes, it works only with 100% binary ones. But if they contain further parts, you can easily adapt it.

Related

Is it possible to pass a String to an AUAudioUnit as a parameter

I am currently working on a AUAudioUnit (AUv3) which requires to load a file located in the Host app's bundle.
This would need to pass the file path (ie: string value) to the Audio Unit as parameter, but I couldn't see how to do this with AUParameter since it seems to only supports Float values (AUValue).
Does anyone know if it's possible ? and how ?
Thanks a lot !
For basic of working with audio engine start with WWDC videos like wwdc 502
For sample code, you can find it here at shlab
An AUParameterGroups allows one to pass multiple parameters. And one can encode pretty much anything in a large enough array of values. A C string is just an array of bits.

Decrypt AES-256-CBC String (need IV, string/data format?)

I've been going around in circles from Apple's CCCrypto docs, frameworks and other SO answers and am not making any headway.
I think I need to figure out how to get a IV from an encrypted string that I receive.
I receive a JSON payload which contains a String. That string is encrypted in AES-256-CBC. (From a Laravel PHP instance that I think uses OpenSSL). The string itself, decrypted, is another JSON object.
I have a pre-defined key.
The string I receive looks something like:
eJahdkawWKajashwlkwAkajsne8ehAhdhsiwkdkdhwNIEhHEheLlwhwlLLLLhshnNWhwhabwiIWHWHwh=
(but is a lot longer).
I'm trying to use this answer here: Issue using CCCrypt (CommonCrypt) in Swift
But am a) unsure if I'm properly converting the string to data and b) how to get the IV (initialization vector) from the string I receive.
Using that answer I do get "success" however when I try to pass it to the NSJSONSerailizer I never got a good result (it always fails) but I do get data out - I think it's garbage.
Edit:
I really mis-understood my original problem - I was receiving a base64 encoded string that I needed to decode into JSON (which went fine). Then using the linked answer and importing CommonCrypto I thought I'd be able to get usable data but I am not. #Rob Napier 's answer is extremely helpful. I think my problem is that the instance of laravel in question is using OpenSSL.
There is no really commonly used standard format for AES encrypted data (there are several "standard formats" but they're not commonly used....) The only way to know how the data you have is encrypted is to look at the documentation for the data format, or failing that, the encrypting code itself.
In good encryption formats, the IV is sent along with the data. But in many common (insecure) formats, there is a hard-coded IV (sometimes 16 bytes of 0x00). If there's a password, you also need to find out how they've converted the password to a key (there are several ways to do this, some good, some horrible). In a good format, the key derivation may include some random "salt" that you need to extract from the data. You'll also need to know if there is an HMAC or similar authentication (which might be stored at the beginning or the end of the data, and may include its own salt).
There just isn't any good way to know without documentation from the sender. Any decently encrypted format is going to look like random noise, so figuring it out just by looking at the final message is pretty hard.
If this comes out of Laravel's encrypt function, then that seems to be ultimately this code:
public function encrypt($value)
{
$iv = mcrypt_create_iv($this->getIvSize(), $this->getRandomizer());
$value = base64_encode($this->padAndMcrypt($value, $iv));
// Once we have the encrypted value we will go ahead base64_encode the input
// vector and create the MAC for the encrypted value so we can verify its
// authenticity. Then, we'll JSON encode the data in a "payload" array.
$mac = $this->hash($iv = base64_encode($iv), $value);
return base64_encode(json_encode(compact('iv', 'value', 'mac')));
}
If this is correct, then you should have been passed base64-encoded JSON with three fields: the IV (iv), the ciphertext (value), and what looks like an HMAC encrypted using the same key as the plaintext (mac). The data you've given above doesn't look like JSON at all (even after base-64 decoding).
This assumes that the caller used this encrypt function, though. There are many, many ways to encrypt, though, so you need to know how the actual server you're talking to did it.

AES encryption security provider error

Ok. I have experienced this problem for quite sometime. Feeling like I am getting close, just need to be pointed in the right direction. So I am using this cool third party library called FBEncryptorAE:
NSString * encryptedMessage = [FBEncryptorAES encryptBase64String:localQuery keyString:key separateLines:NO];
When I post this encrypted query up to my server, I get the following error:
The AES/CBC/PKCS7Padding algorithm is not supported by the Security Provider you have chosen
Here's what my constraints are:
128 bit key
AES/CBC/PKCS5Padding, Base64
coldfusion
Based off of my readings, PKCS5Padding/ PKCS7Padding are the same thing?? If someone could be kind and help me understand:
Why I am getting the error.
Is there sample code I can view based off of my constraints I have? Appreciate any help.
PKCS5Padding and PKCS7Padding produce the same result for AES, are essentially the same.
If you are using CBC an iv is required. How is the iv made the same for both encryption on iOS and decryption on the server? FBEncryptorAES has iv capability but only for (raw data) not (base64) so it is defaulting to "nil" (from the docs). You must get this correct. Since FBEncryptorAES does not support what you need you need to use the (raw data) API and then Base64 encode with the NSData method base64EncodedDataWithOptions:.
Ensure that the key and iv are exactly the required size, for AES128 that is 16 bytes for each. Some wrappers expand undersize keys but there is no standard for that, Common Crypto does not.
Hex dump the input and outputs of all all parameters and data on both sides to ensure they match.
The problem with wrappers is that they are rather opaque as to what is actually being done and that can create interoperability problems. For this reason I always use Common Crypto and the NSData base64 encoding/decoding so I know exactly what is being done.

upload image from blackberry

On my code I got a image from camera but I want to upload it on the server, I convert the image to byte array I sent it to the url of php server can any one tell me Which type of code I have to write.
One problem is that the byte array data is 11 character in length my PM told me that the byte you got is too small
I got the byte array as follows
[B#f359616f
when i run this code at php side the imagecreatefromstring($images); not create the image
Any code plz help me
It looks like you're calling 'toString()' on a byte array. This means you are calling the default implementation of toString provided by the VM, which is to format the type name, then '#' then some object specific int, likely the object identity hash code.
Typically, StackOverflow questions include source code. In this case, you would want to include the function that is uploading the image data. People helping you would be interested in the datatypes involved, and how you are formatting and delivering that data to the server's php script.

SHA256 implementation using Base64 for input and output

I've been asked to develop the company's backoffice for the iPad and, while developing the login screen, I've ran into an issue with the authentication process.
The passwords are concatenated with a salt, hashed using SHA-256 and stored in the database.
The backoffice is Flash-based and uses the as3crypto library to hash then password+salt and my problem is that the current implementation uses Base64 for both input and output.
This site demonstrates how this can be done: just select Hash and select Base64 for both input and output format and fire away. So far, all my attempts have yielded different results from the ones this site (and the backoffice code) give me.
While I think that in theory it should be relatively simply:
Base64 encode the pass+salt
Hash it using SHA-256
Base64 encode the result again
so far I haven't been able to do this and I'm getting quite the headache to be honest.
My code is becoming a living maze, i'll have to redo-it tomorrow I reckon.
Any ideas?
Cheers and thanks in advance
PS: Here's the Backoffice's Flash code for generating hashed passwords by the way:
var currentResult:ByteArray;
var hash:IHash = Crypto.getHash('sha256');
var data:ByteArray = Base64.decodeToByteArray(str + vatel);
currentResult = hash.hash(data);
return Base64.encodeByteArray(currentResult).toString();
The backoffice code does not do
Base64 encode the pass+salt
Hash it using SHA-256
Base64 encode the result again
(as you wrote above)
Instead, what it does is
Base64 decode the pass+salt string into a byte array
Hash the byte array using SHA-256
Base64 encode the byte array, returning a string
As per step 1 above, it's a unclear what kind of character encoding the input strings uses. You need to make sure that both systems use the same encoding for the input strings! UTF8, UTF16-LE or UTF16-BE makes a world of a difference in this case!
Start by finding out the correct character encoding to use on the iOS side.
Oh, and Matt Gallagher has written an easy to use wrapper class for hashes to use on iOS, HashValue.m, I've used it with good results.

Resources